Repository: xt-sys/exectos Branch: master Commit: 19092eda2ebf Files: 347 Total size: 2.8 MB Directory structure: gitextract_3qi0z4ew/ ├── .clangd ├── .github/ │ ├── CODEOWNERS │ ├── ISSUE_TEMPLATE.md │ ├── PULL_REQUEST_TEMPLATE.md │ └── workflows/ │ └── build.yml ├── .gitignore ├── CMakeLists.txt ├── CONTRIBUTING.md ├── COPYING.md ├── ExectOS.code-workspace ├── README.md ├── boot/ │ ├── CMakeLists.txt │ ├── bootdata/ │ │ ├── CMakeLists.txt │ │ └── xtldr/ │ │ ├── CMakeLists.txt │ │ └── xtldr.ini │ ├── bootsect/ │ │ ├── CMakeLists.txt │ │ ├── amd64/ │ │ │ └── cpu.S │ │ ├── espboot.S │ │ ├── i686/ │ │ │ └── cpu.S │ │ └── mbrboot.S │ └── xtldr/ │ ├── CMakeLists.txt │ ├── README.md │ ├── arch/ │ │ ├── amd64/ │ │ │ └── memory.cc │ │ └── i686/ │ │ └── memory.cc │ ├── biosutil.cc │ ├── bootutil.cc │ ├── config.cc │ ├── console.cc │ ├── data.cc │ ├── debug.cc │ ├── efiutils.cc │ ├── includes/ │ │ ├── libxtos.hh │ │ └── xtldr.hh │ ├── library/ │ │ └── modproto.cc │ ├── memory.cc │ ├── modules/ │ │ ├── CMakeLists.txt │ │ ├── acpi/ │ │ │ ├── CMakeLists.txt │ │ │ ├── acpi.cc │ │ │ ├── data.cc │ │ │ └── includes/ │ │ │ └── acpi.hh │ │ ├── beep/ │ │ │ ├── CMakeLists.txt │ │ │ ├── beep.cc │ │ │ ├── data.cc │ │ │ └── includes/ │ │ │ └── beep.hh │ │ ├── chainldr/ │ │ │ ├── CMakeLists.txt │ │ │ ├── chainldr.cc │ │ │ ├── data.cc │ │ │ └── includes/ │ │ │ └── chainldr.hh │ │ ├── dummy/ │ │ │ ├── CMakeLists.txt │ │ │ ├── data.cc │ │ │ ├── dummy.cc │ │ │ └── includes/ │ │ │ └── dummy.hh │ │ ├── framebuf/ │ │ │ ├── CMakeLists.txt │ │ │ ├── data.cc │ │ │ ├── framebuf.cc │ │ │ └── includes/ │ │ │ └── framebuf.hh │ │ ├── pecoff/ │ │ │ ├── CMakeLists.txt │ │ │ ├── data.cc │ │ │ ├── includes/ │ │ │ │ └── pecoff.hh │ │ │ └── pecoff.cc │ │ └── xtos_o/ │ │ ├── CMakeLists.txt │ │ ├── amd64/ │ │ │ └── memory.cc │ │ ├── data.cc │ │ ├── i686/ │ │ │ └── memory.cc │ │ ├── includes/ │ │ │ └── xtos.hh │ │ └── xtos.cc │ ├── protocol.cc │ ├── shell.cc │ ├── textui.cc │ ├── volume.cc │ └── xtldr.cc ├── configure.ps1 ├── configure.sh ├── drivers/ │ ├── CMakeLists.txt │ └── ntosdrv/ │ ├── CMakeLists.txt │ ├── ntosdrv.cc │ ├── ntosdrv.spec │ └── rtl.cc ├── sdk/ │ ├── CMakeLists.txt │ ├── cmake/ │ │ ├── README.md │ │ ├── baseaddress/ │ │ │ ├── amd64.cmake │ │ │ └── i686.cmake │ │ ├── emulation.cmake │ │ ├── functions.cmake │ │ ├── toolchain.cmake │ │ ├── version/ │ │ │ └── xtver.h.cmake │ │ ├── version.cmake │ │ └── xtchain.cmake │ ├── firmware/ │ │ ├── README.md │ │ ├── bochsrc_amd64.cfg │ │ ├── bochsrc_i686.cfg │ │ ├── ovmf_amd64.fd │ │ └── ovmf_i686.fd │ ├── xtadk/ │ │ ├── CMakeLists.txt │ │ ├── amd64/ │ │ │ └── ke.cc │ │ ├── i686/ │ │ │ └── ke.cc │ │ └── includes/ │ │ └── adkdefs.h │ └── xtdk/ │ ├── README.md │ ├── amd64/ │ │ ├── artypes.h │ │ ├── hlfuncs.h │ │ ├── hltypes.h │ │ ├── ketypes.h │ │ ├── mmtypes.h │ │ └── xtstruct.h │ ├── blfuncs.h │ ├── bltarget.h │ ├── bltypes.h │ ├── exfuncs.h │ ├── extypes.h │ ├── hlfuncs.h │ ├── hltypes.h │ ├── i686/ │ │ ├── artypes.h │ │ ├── hlfuncs.h │ │ ├── hltypes.h │ │ ├── ketypes.h │ │ ├── mmtypes.h │ │ └── xtstruct.h │ ├── iotypes.h │ ├── kdfuncs.h │ ├── kdtypes.h │ ├── kefuncs.h │ ├── ketypes.h │ ├── ldrtypes.h │ ├── mmfuncs.h │ ├── mmtypes.h │ ├── potypes.h │ ├── pstypes.h │ ├── rtlfuncs.h │ ├── rtltypes.h │ ├── xtbase.h │ ├── xtblapi.h │ ├── xtcompat.h │ ├── xtdebug.h │ ├── xtdefs.h │ ├── xtfont.h │ ├── xtfw.h │ ├── xtglyph.h │ ├── xtguid.h │ ├── xtimage.h │ ├── xtkmapi.h │ ├── xtstatus.h │ ├── xtstruct.h │ ├── xttarget.h │ ├── xttypes.h │ └── xtuefi.h └── xtoskrnl/ ├── CMakeLists.txt ├── README.md ├── ar/ │ ├── amd64/ │ │ ├── archsup.S │ │ ├── cpufunc.cc │ │ ├── data.cc │ │ ├── procsup.cc │ │ └── traps.cc │ └── i686/ │ ├── archsup.S │ ├── cpufunc.cc │ ├── data.cc │ ├── procsup.cc │ └── traps.cc ├── ex/ │ ├── exports.cc │ └── rundown.cc ├── hl/ │ ├── acpi.cc │ ├── amd64/ │ │ ├── cpu.cc │ │ ├── firmware.cc │ │ ├── ioport.cc │ │ ├── irq.cc │ │ ├── pic.cc │ │ ├── rtc.cc │ │ ├── runlevel.cc │ │ └── timer.cc │ ├── cport.cc │ ├── data.cc │ ├── exports.cc │ ├── fbdev.cc │ ├── i686/ │ │ ├── cpu.cc │ │ ├── firmware.cc │ │ ├── ioport.cc │ │ ├── irq.cc │ │ ├── pic.cc │ │ ├── rtc.cc │ │ ├── runlevel.cc │ │ └── timer.cc │ ├── init.cc │ ├── ioreg.cc │ └── x86/ │ ├── cpu.cc │ ├── firmware.cc │ ├── pic.cc │ ├── rtc.cc │ └── timer.cc ├── includes/ │ ├── ar/ │ │ ├── amd64/ │ │ │ ├── asmsup.hh │ │ │ ├── cpufunc.hh │ │ │ ├── procsup.hh │ │ │ └── traps.hh │ │ └── i686/ │ │ ├── asmsup.hh │ │ ├── cpufunc.hh │ │ ├── procsup.hh │ │ └── traps.hh │ ├── ar.hh │ ├── ex/ │ │ └── rundown.hh │ ├── ex.hh │ ├── hl/ │ │ ├── acpi.hh │ │ ├── cport.hh │ │ ├── cpu.hh │ │ ├── fbdev.hh │ │ ├── firmware.hh │ │ ├── init.hh │ │ ├── ioport.hh │ │ ├── ioreg.hh │ │ ├── irq.hh │ │ ├── pic.hh │ │ ├── rtc.hh │ │ ├── runlevel.hh │ │ └── timer.hh │ ├── hl.hh │ ├── kd/ │ │ ├── dbg.hh │ │ └── dbgio.hh │ ├── kd.hh │ ├── ke/ │ │ ├── apc.hh │ │ ├── bootinfo.hh │ │ ├── crash.hh │ │ ├── dispatch.hh │ │ ├── dpc.hh │ │ ├── event.hh │ │ ├── guard.hh │ │ ├── kprocess.hh │ │ ├── krnlinit.hh │ │ ├── kthread.hh │ │ ├── kubsan.hh │ │ ├── proc.hh │ │ ├── runlevel.hh │ │ ├── semphore.hh │ │ ├── shdata.hh │ │ ├── spinlock.hh │ │ ├── sysres.hh │ │ ├── systime.hh │ │ └── timer.hh │ ├── ke.hh │ ├── mm/ │ │ ├── alloc.hh │ │ ├── amd64/ │ │ │ ├── pagemap.hh │ │ │ ├── paging.hh │ │ │ └── pte.hh │ │ ├── colors.hh │ │ ├── guard.hh │ │ ├── hlpool.hh │ │ ├── i686/ │ │ │ ├── pagemap.hh │ │ │ ├── paging.hh │ │ │ └── pte.hh │ │ ├── kpool.hh │ │ ├── mmgr.hh │ │ ├── pfault.hh │ │ ├── pfn.hh │ │ └── pool.hh │ ├── mm.hh │ ├── po/ │ │ └── idle.hh │ ├── po.hh │ ├── rtl/ │ │ ├── amd64/ │ │ │ └── intrin.hh │ │ ├── atomic.hh │ │ ├── bitmap.hh │ │ ├── dispatch.hh │ │ ├── endian.hh │ │ ├── guid.hh │ │ ├── i686/ │ │ │ └── intrin.hh │ │ ├── llist.hh │ │ ├── math.hh │ │ ├── memory.hh │ │ ├── sha1.hh │ │ ├── slist.hh │ │ ├── string.hh │ │ ├── time.hh │ │ └── widestr.hh │ ├── rtl.hh │ └── xtos.hh ├── kd/ │ ├── data.cc │ ├── dbgio.cc │ └── exports.cc ├── ke/ │ ├── amd64/ │ │ ├── dispatch.cc │ │ ├── krnlinit.cc │ │ ├── kthread.cc │ │ └── proc.cc │ ├── apc.cc │ ├── bootinfo.cc │ ├── crash.cc │ ├── data.cc │ ├── dispatch.cc │ ├── dpc.cc │ ├── event.cc │ ├── exports.cc │ ├── i686/ │ │ ├── dispatch.cc │ │ ├── krnlinit.cc │ │ ├── kthread.cc │ │ └── proc.cc │ ├── kprocess.cc │ ├── krnlinit.cc │ ├── kthread.cc │ ├── kubsan.cc │ ├── runlevel.cc │ ├── semphore.cc │ ├── shdata.cc │ ├── spinlock.cc │ ├── sysres.cc │ ├── systime.cc │ └── timer.cc ├── mm/ │ ├── alloc.cc │ ├── amd64/ │ │ ├── mmgr.cc │ │ ├── pagemap.cc │ │ ├── paging.cc │ │ ├── pfault.cc │ │ ├── pfn.cc │ │ ├── pool.cc │ │ └── pte.cc │ ├── colors.cc │ ├── data.cc │ ├── exports.cc │ ├── hlpool.cc │ ├── i686/ │ │ ├── mmgr.cc │ │ ├── pagemap.cc │ │ ├── paging.cc │ │ ├── pfault.cc │ │ ├── pfn.cc │ │ ├── pool.cc │ │ └── pte.cc │ ├── kpool.cc │ ├── mmgr.cc │ ├── paging.cc │ ├── pfn.cc │ ├── pool.cc │ └── pte.cc ├── po/ │ └── idle.cc ├── rtl/ │ ├── amd64/ │ │ ├── dispatch.cc │ │ ├── exsup.cc │ │ └── intrin.cc │ ├── atomic.cc │ ├── bitmap.cc │ ├── data.cc │ ├── endian.cc │ ├── exports.cc │ ├── guid.cc │ ├── i686/ │ │ ├── dispatch.cc │ │ ├── exsup.cc │ │ └── intrin.cc │ ├── llist.cc │ ├── math.cc │ ├── memory.cc │ ├── sha1.cc │ ├── slist.cc │ ├── string.cc │ ├── time.cc │ └── widestr.cc └── xtoskrnl.spec ================================================ FILE CONTENTS ================================================ ================================================ FILE: .clangd ================================================ Diagnostics: Suppress: 'pp_including_mainfile_in_preamble' InlayHints: Enabled: No ================================================ FILE: .github/CODEOWNERS ================================================ * @Belliash ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ ## ExectOS Information - ExectOS Version (or commit ref): - System Architecture (eg. i686, amd64, ...): - Hypervisor Information (use `[X]`): - [ ] Bare metal - [ ] Bochs - [ ] Hyper-V - [ ] Qemu (KVM) - [ ] Qemu (TCG) - [ ] VirtualBox - [ ] VmWare - [ ] Other ## Your problem description Please provide here as much information as possible, including a code snippet if applicable. ## Expected results Describe here, what output and/or software behave did you expect. ## Current results Provide here current result and program output. ## Debug backtrace and logs Provide here logs and debug bugtrace if applicable. ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ ## Purpose _Do a quick recap of your work here._ _If it fixes some bug, don't forget to mention it here._ ## Proposed changes _Describe what you propose to change/add/fix with this pull request._ - - ## TODO _Use a TODO when your pull request is Work in Progress._ - [ ] - [ ] - [ ] ## Agreements - [ ] I have read the Contributors License Agreement and I consent to those terms. ================================================ FILE: .github/workflows/build.yml ================================================ name: Builds run-name: ${{ github.actor }} runs Gitea Actions on: [push] jobs: ExectOS: strategy: matrix: arch: [amd64, i686] build: [debug, release] runs-on: oscw container: image: codingworkshop/oscw-runner:latest steps: - name: Clone repository uses: actions/checkout@v3 with: fetch-depth: 0 - name: Build ExectOS run: | echo "charch ${{ matrix.arch }} && chbuild ${{ matrix.build }} && ./configure.sh && cd build-${{ matrix.arch }}-${{ matrix.build }} && xbuild -v && xbuild diskimg -v" > build.cmds xtchain < build.cmds - name: Publish binaries if: ${{ github.ref == 'refs/heads/master' }} env: OSCW_ARTIFACTS_HOSTNAME: ${{ secrets.OSCW_ARTIFACTS_HOSTNAME }} OSCW_ARTIFACTS_USERNAME: ${{ secrets.OSCW_ARTIFACTS_USERNAME }} OSCW_ARTIFACTS_USERKEY: ${{ secrets.OSCW_ARTIFACTS_USERKEY }} run: | tar -I 'gzip' -cpf ExectOS-$(date +'%Y%m%d')-${GITHUB_SHA:0:10}-${{ matrix.arch }}-${{ matrix.build }}-bin.tar.gz -C build-${{ matrix.arch }}-${{ matrix.build }}/output/binaries . tar -I 'gzip' -cpf ExectOS-$(date +'%Y%m%d')-${GITHUB_SHA:0:10}-${{ matrix.arch }}-${{ matrix.build }}-sdk.tar.gz -C build-${{ matrix.arch }}-${{ matrix.build }}/output/sdk . tar -I 'gzip' -cpf ExectOS-$(date +'%Y%m%d')-${GITHUB_SHA:0:10}-${{ matrix.arch }}-${{ matrix.build }}-sym.tar.gz -C build-${{ matrix.arch }}-${{ matrix.build }}/output/symbols . gzip -c build-${{ matrix.arch }}-${{ matrix.build }}/output/disk.img > ExectOS-$(date +'%Y%m%d')-${GITHUB_SHA:0:10}-${{ matrix.arch }}-${{ matrix.build }}.img.gz artifact_publish "ExectOS-$(date +'%Y%m%d')-${GITHUB_SHA:0:10}-${{ matrix.arch }}-${{ matrix.build }}*.gz" ExectOS ================================================ FILE: .gitignore ================================================ .cache .vscode build build-* ================================================ FILE: CMakeLists.txt ================================================ # Minimum CMake version requirement cmake_minimum_required(VERSION 3.19.0) # Lowercase target architecture string(TOLOWER ${ARCH} ARCH) # Validate and set architectures specific definitions if(ARCH STREQUAL "i686") add_definitions(-D__i386__ -D__i686__) elseif(ARCH STREQUAL "amd64") add_definitions(-D__amd64__ -D__x86_64__) else() message(FATAL_ERROR "Unknown target architecture (${ARCH}) set!") endif() # Print target architecture message("-- Target architecture: ${ARCH}") # Set the build type if(NOT BUILD_TYPE) set(BUILD_TYPE DEBUG) endif() string(TOUPPER ${BUILD_TYPE} BUILD_TYPE) # Set build type specific definitions if(BUILD_TYPE STREQUAL "DEBUG") add_definitions(-DDBG=1) set(CMAKE_BUILD_TYPE DEBUG) else() set(BUILD_TYPE RELEASE) set(CMAKE_BUILD_TYPE NONE) endif() # Print build type message("-- Target build type: ${BUILD_TYPE}") # Set toolchain file set(CMAKE_TOOLCHAIN_FILE "sdk/cmake/toolchain.cmake") # Set project name project(EXECTOS) # Load all the CMake SDK include(sdk/cmake/baseaddress/${ARCH}.cmake) include(sdk/cmake/emulation.cmake) include(sdk/cmake/functions.cmake) include(sdk/cmake/version.cmake) include(sdk/cmake/xtchain.cmake) # Enable compilers enable_language(ASM C CXX) # Add project specific definitions add_definitions(-D__XTOS__) add_definitions(-DXTOS_SOURCE_DIR="${EXECTOS_SOURCE_DIR}") add_definitions(-DXTOS_BINARY_DIR="${EXECTOS_BINARY_DIR}") # Add assembler flags add_compiler_asmflags(-D__XTOS_ASSEMBLER__) # Compute __FILE__ definition file(RELATIVE_PATH _PATH_PREFIX ${EXECTOS_BINARY_DIR} ${EXECTOS_SOURCE_DIR}) add_compiler_flags(-D__RELFILE__="&__FILE__[__FILE__[0] == '.' ? sizeof \\\"${_PATH_PREFIX}\\\" - 1 : sizeof XTOS_SOURCE_DIR]") # Set the virtual disk image size (in MiB) set_disk_image_size(48) # Build all subprojects add_subdirectory(boot) add_subdirectory(drivers) add_subdirectory(sdk) add_subdirectory(xtoskrnl) ================================================ FILE: CONTRIBUTING.md ================================================ ## Contributing We appreciate any form for contribution you want to make to the project! ExectOS is purely driven by passion, and we dedicate any and all available spare time to this project. Contributions of any kind are deerly welcome, but should follow the below guidelines. ## Where To Start? There is a ton of work to do in ExectOS and we appreciate any help. If you are interested in writing features, porting drivers, fixing bugs, writing tests, creating documentation, or helping out in any other way, we would love the help. ## Wish List If you are looking for a way to contribute, but you are not sure where to start, check our list of [open issues](https://git.codingworkshop.eu.org/xt-sys/exectos/issues). If you find interesting task and you are serious about tackling one, feel free to contact us. We will be able to provide a more detailed information and suggestions towards getting started. ## Reporting Bugs When submitting issues, please take care that the bug report is not a duplicate of an already existing, open issue. Please follow the template specified for issues. ## Feature Requests ExectOS is currently in early development stage, thus we do not accept feature requests yet. We focus currently on the system core components. ## Submissions If you want to contribute on the project please fork the repository, and contribute by opening a [Pull Request](https://git.codingworkshop.eu.org/xt-sys/exectos/pulls). There is a pull request template you can use. While doing this, please follow few, simple rules: * Provide your real name and e-mail address * Do not commit code that doesn't compile * Test your changes before committing * Always add descriptive log messages * Don't mix formatting changes with code changes Good luck! ================================================ FILE: COPYING.md ================================================ # GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 [Free Software Foundation, Inc.](http://fsf.org/) Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. ## Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: 1. assert copyright on the software, and 2. offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. ## TERMS AND CONDITIONS ### 0. Definitions. *This License* refers to version 3 of the GNU General Public License. *Copyright* also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. *The Program* refers to any copyrightable work licensed under this License. Each licensee is addressed as *you*. *Licensees* and *recipients* may be individuals or organizations. To *modify* a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a *modified version* of the earlier work or a work *based on* the earlier work. A *covered work* means either the unmodified Program or a work based on the Program. To *propagate* a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To *convey* a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays *Appropriate Legal Notices* to the extent that it includes a convenient and prominently visible feature that 1. displays an appropriate copyright notice, and 2. tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. ### 1. Source Code. The *source code* for a work means the preferred form of the work for making modifications to it. *Object code* means any non-source form of a work. A *Standard Interface* means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The *System Libraries* of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A *Major Component*, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The *Corresponding Source* for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. ### 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. ### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. ### 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. ### 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: - a) The work must carry prominent notices stating that you modified it, and giving a relevant date. - b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to *keep intact all notices*. - c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. - d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an *aggregate* if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. ### 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: - a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. - b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either 1. a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or 2. access to copy the Corresponding Source from a network server at no charge. - c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. - d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. - e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A *User Product* is either 1. a *consumer product*, which means any tangible personal property which is normally used for personal, family, or household purposes, or 2. anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, *normally used* refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. *Installation Information* for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. ### 7. Additional Terms. *Additional permissions* are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: - a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or - b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or - c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or - d) Limiting the use for publicity purposes of names of licensors or authors of the material; or - e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or - f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered *further restrictions* within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. ### 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated - a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and - b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. ### 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. ### 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An *entity transaction* is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. ### 11. Patents. A *contributor* is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's *contributor version*. A contributor's *essential patent claims* are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, *control* includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a *patent license* is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To *grant* such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either 1. cause the Corresponding Source to be so available, or 2. arrange to deprive yourself of the benefit of the patent license for this particular work, or 3. arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. *Knowingly relying* means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is *discriminatory* if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license - a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or - b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. ### 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. ### 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. ### 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License *or any later version* applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. ### 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ### 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ### 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. ## END OF TERMS AND CONDITIONS ### ### How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the *copyright* line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w` and `show c` should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an *about box*. You should also get your employer (if you work as a programmer) or school, if any, to sign a *copyright disclaimer* for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/). The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read [http://www.gnu.org/philosophy/why-not-lgpl.html](http://www.gnu.org/philosophy/why-not-lgpl.html). ================================================ FILE: ExectOS.code-workspace ================================================ { "folders": [ { "path": "." } ], "settings": { "clangd.arguments": [ "--compile-commands-dir=${workspaceFolder}/build/", "--header-insertion=never", "--enable-config", "--log=verbose" ], "editor.rulers": [ 120 ], "terminal.integrated.profiles.linux": { "xtchain": { "path": "xtchain" } }, "terminal.integrated.defaultProfile.linux": "xtchain", } } ================================================ FILE: README.md ================================================

GIT Repository Commits Build Status CI/CD Artifacts License AI Assisted Sponsor Discord

--- # ExectOS Operating System ExectOS is an open-source, general purpose operating system written from scratch. It aims to be modular, maintainable and compatible with existing software. It implements a brand new XT architecture and features own native application interface. On the backend, it contains a powerful driver model between device drivers and the kernel, that enables kernel level components to be upgraded without a need to recompile all drivers. # XT Architecture ExectOS is a preemptive, reentrant multitasking operating system that implements the XT architecture which derives from NT architecture. It is modular, and consists of two main layers: microkernel and user modes. Its' kernel mode has full access to the hardware and system resources and runs code in a protected memory area. It consists of executive services, which is itself made up on many modules that do specific tasks, a kernel and drivers. Unlike the NT, system does not feature a separate Hardware Abstraction Layer (HAL) between the physical hardware and the rest of the OS. Instead, XT architecture integrates a hardware specific code with the kernel. The user mode is made up of subsystems and it has been designed to run applications written for many different types of operating systems. This allows to implement any environment subsystem to support applications that are strictly written to the corresponding standard (eg. DOS, or POSIX). # Features * Modern, EFI enabled operating system * Runs on x86 and x86_64 architectures * Portable to other architectures * Modular design, open-source project * Own drivers for commonly used devices * NT drivers compatibility layer # Requirements ExectOS is currently in a very early stage of development, so its specific requirements are not fully defined yet. However, based on the current design, it requires modern EFI hardware. You cannot boot ExectOS on a legacy BIOS right now, but there are plans to add BIOS support in the future. # Source structure | Directory | Description | |------------------|--------------------------------------------------------------| | boot/bootdata | default configuration and data needed to boot XTOS | | boot/bootsect | boot sector code (MBR & VBR) initializing the boot process | | boot/xtldr | XTOS boot loader source code | | drivers | XT native drivers source code | | sdk/cmake | host toolchain configuration and build-related functions | | sdk/firmware | firmware enabling XTOS to boot on virtual machines | | sdk/xtdk | XT Software Development Kit headers | | services | integral subsystems services source code | | subsystems | environment subsystems source code | | xtoskrnl | XTOS kernel source code | # Build XTOS can only be built using [XTchain](https://git.codingworkshop.eu.org/xt-sys/xtchain), a dedicated toolchain designed specifically for compiling XT software. XTChain is currently available for both Linux and Windows. Detailed instructions on how to configure and run XTChain can be found [here](https://exectos.eu.org/contributing/setting-up-xtchain). With the XTchain environment already running, navigate to the directory containing the ExectOS source code and use the following commands to set the target build architecture and configure the sources: ``` charch [i686|amd64] chbuild [DEBUG|RELEASE] ./configure.sh ``` Once the sources are configured, enter the build directory and compile the source code: ``` cd build xbuild ``` It is also possible to build a disk image ready to use with QEMU with the following command: ``` xbuild diskimg ``` # Contributing There is a ton of work to do in ExectOS and we appreciate any help. If you are interested in writing features, porting drivers, fixing bugs, writing tests, creating documentation, or helping out in any other way, we would love the help. More details on how to contrubite can be found it [CONTRIBUTING.md](CONTRIBUTING.md) file. # Licensing ExectOS is licensed to the public under the terms of the GNU General Public License, version 3. For more detailed information check the [COPYING.md](COPYING.md) file. # GIT Mirrors * Main GIT Repository: https://git.codingworkshop.eu.org/xt-sys/exectos * GitHub Mirror: https://github.com/xt-sys/exectos * GitLab Mirror: https://gitlab.com/xt-sys/exectos # Contact * Discord Server: https://discord.com/invite/zBzJ5qMGX7 ================================================ FILE: boot/CMakeLists.txt ================================================ add_subdirectory(bootdata) add_subdirectory(bootsect) add_subdirectory(xtldr) ================================================ FILE: boot/bootdata/CMakeLists.txt ================================================ add_subdirectory(xtldr) ================================================ FILE: boot/bootdata/xtldr/CMakeLists.txt ================================================ set_install_file(xtldr.ini efi/boot/xtldr) ================================================ FILE: boot/bootdata/xtldr/xtldr.ini ================================================ # This is the XT Boot Loader (XTLDR) configuration file. It follows an INI format and is divided into sections, which # contain a properties. Each property has a name and value delimited by an equal (=) character. Comments must start # with a semicolon (;) or a hash character (#) and run to the end of the line. # # Basic section is [XTLDR] which contains a bootloader specific options: # Debug - enables the debugging port and consists of two comma-separated parameters: com port and baud rate; # it is also possible to specify custom port address with: COM0:[address],[baud_rate] # Default - specifies which operating system listen in config file will be started if no choice is made # KeepLastBoot - specifies whether last booted OS should be stored in NVRAM and booted automatically next time, or not; # this parameter takes 'true' or 'false' value # Modules - supplies a list of modules that will be loaded in orded to extend XTLDR functionality # Timeout - sets the countdown timer (in seconds) before the default OS get started automatically # Tune - plays a tune on the pcspeaker right before the XTLDR boot menu shows up # # Another type of section is [OS-Section] which adds a new position (operating system) to the boot menu. Each type # of the operating system provides a set of available parameters. If unsupported option is added, it is being ignored # by the XT Boot Loader. The available options are: # BootModules - supplies a list of additional modules that will be loaded just before invoking the boot protocol # SystemName - sets a long operating system name that will be shown on the boot menu # SystemType - specifies an OS type from a predefined list of supported boot protocols # SystemPath - the ARC path, eg. multi(0)disk(0)rdisk(0)partition(1) # KernelFile - sets kernel filename with optional path relative to SystemPath # InitrdFile - sets initramfs image filename with optional path relative to SystemPath # HalFile - sets HAL filename with optional path relative to SystemPath # Parameters - specifies extra boot options for the kernel [XTLDR] Debug=COM1,115200 Default=ExectOS KeepLastBoot=TRUE Modules=beep Timeout=10 Tune=400 880 2 988 2 783 2 392 2 587 3 [ExectOS] SystemName="ExectOS Operating System" SystemType=XTOS BootModules=xtos_o SystemPath=multi(0)disk(0)rdisk(0)partition(1)/ExectOS KernelFile=xtoskrnl.exe Parameters=DEBUG=COM1,115200 [ExectOS_FBDEBUG] SystemName="ExectOS Operating System (FBDEBUG)" SystemType=XTOS BootModules=xtos_o SystemPath=multi(0)disk(0)rdisk(0)partition(1)/ExectOS KernelFile=xtoskrnl.exe Parameters=DEBUG=COM1,115200;SCREEN [ExectOS_NOXPA] SystemName="ExectOS Operating System (NOXPA)" SystemType=XTOS BootModules=xtos_o SystemPath=multi(0)disk(0)rdisk(0)partition(1)/ExectOS KernelFile=xtoskrnl.exe Parameters=DEBUG=COM1,115200 NOXPA [ExectOS_NOXPA_FBDEBUG] SystemName="ExectOS Operating System (NOXPA / FBDEBUG)" SystemType=XTOS BootModules=xtos_o SystemPath=multi(0)disk(0)rdisk(0)partition(1)/ExectOS KernelFile=xtoskrnl.exe Parameters=DEBUG=COM1,115200;SCREEN NOXPA [Windows] SystemName="Microsoft Windows 2000" SystemType=NT50 BootModules=ntos SystemPath=multi(0)disk(0)rdisk(0)partition(2)/Windows KernelFile=ntoskrnl.exe HalFile=hal.dll Parameters=/NOGUIBOOT /MININT [Linux] SystemName="GNU/Linux" SystemType=LINUX BootModules=linux SystemPath=multi(0)disk(0)rdisk(0)partition(3)/boot KernelFile=vmlinuz InitrdFile=initramfs.cpio.gz Parameters=root=/dev/xvda3 rootfstype=ext4 [EFI Shell] SystemName="EFI Shell" SystemType=CHAINLOADER BootModules=chainldr SystemPath=multi(0)disk(0)rdisk(0)partition(1)/efi/boot KernelFile=efishell.efi ================================================ FILE: boot/bootsect/CMakeLists.txt ================================================ # XT Boot Sector PROJECT(BOOTSECT) add_definitions("-DARCH_ESP_SOURCE=\\\"${ARCH}/cpu.S\\\"") # Compile boot sectors compile_bootsector(mbrboot ${BOOTSECT_SOURCE_DIR}/mbrboot.S 0x7C00 Start) compile_bootsector(espboot ${BOOTSECT_SOURCE_DIR}/espboot.S 0x7C00 Start) ================================================ FILE: boot/bootsect/amd64/cpu.S ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: boot/bootsect/amd64/cpu.S * DESCRIPTION: Low-level support for CPU initialization * DEVELOPERS: Aiken Harris */ BuildPageMap: /* Generate page map for first 1GB of memory */ pushaw pushw %es cld movw $(0x1000 / 16), %ax movw %ax, %es xorw %di, %di movl $(0x2000 | 0x07), %eax stosl xorl %eax, %eax movw $1021, %cx rep stosl movw $(0x2000 / 16), %ax movw %ax, %es xorw %di, %di movl $(0x3000 | 0x07), %eax stosl xorl %eax, %eax movw $1021, %cx rep stosl movw $(0x3000 / 16), %ax movw %ax, %es xorw %di, %di movw $512, %cx movl $0x00000083, %eax .BuildPageMapLoop: /* Identity map 512 pages of 2MB */ movl %eax, %es:(%di) addl $2097152, %eax addw $0x08, %di loop .BuildPageMapLoop popw %es popaw ret InitializeCpu: /* Check if CPU supports CPUID, long mode and PAE */ pushal pushfl popl %eax movl %eax, %ebx xorl $0x00200000, %eax pushl %eax popfl pushfl popl %eax cmpl %ebx, %eax je CpuUnsupported movl $0x01, %eax cpuid testl $0x40, %edx jz CpuUnsupported movl $0x80000000, %eax cpuid cmpl $0x80000000, %eax jbe CpuUnsupported movl $0x80000001, %eax cpuid testl $0x20000000, %edx jz CpuUnsupported popal call LoadGdt ret LoadGdt: /* Load Global Descriptor Table */ lgdt .GdtPointer ret RunStage2: /* Switch to long mode and pass control to Stage 2 */ call BuildPageMap call ParseExecutableHeader xorl %edx, %edx pushl %edx pushl %eax cli xorw %ax, %ax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs movw %ax, %ss movl %cr4, %eax orl $0x00A0, %eax movl %eax, %cr4 movl $0x00001000, %eax movl %eax, %cr3 movl $0xC0000080, %ecx rdmsr orl $0x00000100, %eax wrmsr movl %cr0, %eax orl $0x80000001, %eax movl %eax, %cr0 ljmp $0x10, $.Stage2LongMode .code64 .Stage2LongMode: /* Set segments and stack, then jump to Stage 2 */ movw $0x18, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss xorw %ax, %ax movw %ax, %fs movw %ax, %gs popq %rax xorq %rbx, %rbx xorq %rcx, %rcx xorq %rdx, %rdx xorq %rsi, %rsi xorq %rdi, %rdi xorq %rbp, %rbp jmp *%rax .code16 .GdtDescriptor: /* Global Descriptor Table */ .quad 0x0000000000000000 .quad 0x0000000000000000 .quad 0x00AF9A000000FFFF .quad 0x00CF92000000FFFF .quad 0x00009E000000FFFF .quad 0x000092000000FFFF .quad 0x00CF9B000000FFFF .GdtPointer: /* Pointer to Global Descriptor Table */ .word .GdtPointer - .GdtDescriptor - 1 .long .GdtDescriptor .Stage2FileName: /* Name of Stage 2 executable file */ .ascii "BOOTX64 EFI" ================================================ FILE: boot/bootsect/espboot.S ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: boot/bootsect/espboot.S * DESCRIPTION: XT Boot Loader ESP boot code (FAT32) * DEVELOPERS: Aiken Harris */ .text .code16 .global Start Start: /* Jump to the real start to omit the BPB (BIOS Parameter Block) */ jmp RealStart nop /* BIOS Parameter Block */ OsName: .ascii "XTOS " OsVersion: .ascii "1.0" BytesPerSector: .word 512 SectorsPerCluster: .byte 2 ReservedSectors: .word 8 FatCopies: .byte 1 RootDirEntries: .word 1024 TotalSectors: .word 0 MediaType: .byte 0xF8 SectorsPerFat: .word 0 SectorsPerTrack: .word 17 NumberOfHeads: .word 0 HiddenSectors: .long 0 TotalBigSectors: .long 0x200000 BigSectorsPerFat: .long 0x1FE0 ExtendedFlags: .word 0 FsVersion: .word 0 RootDirStartCluster: .long 0 FSInfoSector: .word 0 BackupBootSector: .word 6 Reserved: .fill 12, 1, 0 DriveNumber: .byte 0x80 CurrentHead: .byte 0 Signature: .byte 0x29 SerialNumber: .long 0 VolumeLabel: .ascii "NO NAME " FileSystem: .ascii "FAT32 " RealStart: /* Set segments and stack */ cli cld xorw %ax, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss movw $0x7C00, %bp leaw -16(%bp), %sp sti /* Get drive number */ cmpb $0xFF, DriveNumber - Start(%bp) jne GetDriveParameters movb %dl, DriveNumber - Start(%bp) GetDriveParameters: /* Get drive parameters from the BIOS */ movb DriveNumber - Start(%bp), %dl movb $0x08, %ah movb $0x00, %al int $0x13 jnc GetDriveSize movw $0xFFFF, %cx movb %cl, %dh GetDriveSize: /* Get drive size from the BIOS */ movzbl %dh, %eax incw %ax movzbl %cl, %edx andb $0x3F, %dl mulw %dx xchgb %cl, %ch shrb $0x06, %ch incw %cx movzwl %cx, %ecx mull %ecx movl %eax, %edi VerifyBiosParameterBlock: /* Verify the FAT32 BPB */ cmpw $0x00, SectorsPerFat - Start(%bp) jne FsError cmpw $0x00, FsVersion - Start(%bp) ja FsError ReadExtraCode: /* Read second VBR sector with extra boot code (3 sectors starting from sector 2) */ movl HiddenSectors - Start(%bp), %eax addl $0x02, %eax movw $0x03, %cx xorw %bx, %bx movw %bx, %es movw $0x7E00, %bx call ReadSectors jmp StartExtraCode ReadSectors: /* Check for extended BIOS functions and use it only if available */ pushw %es pushal movb $0x41, %ah movw $0x55AA, %bx movb DriveNumber - Start(%bp), %dl int $0x13 jc .ReadCHS cmpw $0xAA55, %bx jne .ReadCHS testb $0x01, %cl jz .ReadCHS /* Verify drive size and determine whether to use CHS or LBA */ cmpl %edi, %eax jnb .ReadLBA .ReadCHS: /* Read sectors using CHS */ popal .CHSLoop: /* Read sector by sector using CHS */ pushw %cx pushal xorl %edx, %edx movzwl SectorsPerTrack - Start(%bp), %ecx divl %ecx incb %dl movb %dl, %cl movl %eax, %edx shrl $0x10, %edx divw NumberOfHeads - Start(%bp) movb %dl, %dh movb DriveNumber - Start(%bp), %dl movb %al, %ch rorb $0x01, %ah rorb $0x01, %ah orb %ah, %cl movw $0x0201, %ax int $0x13 popal popw %cx jc DiskError incl %eax movw %es, %dx addw $0x20, %dx movw %dx, %es loop .CHSLoop popw %es ret .ReadLBA: /* Prepare DAP packet and read sectors using LBA */ popal pushw %cx pushal pushw $0x00 pushw $0x00 pushl %eax pushw %es pushw %bx pushw %cx pushw $0x10 movw %sp, %si movb DriveNumber - Start(%bp), %dl movb $0x42, %ah int $0x13 jc DiskError addw $0x10, %sp popal popw %si pushw %bx movzwl %si, %ebx addl %ebx, %eax shll $0x05, %ebx movw %es, %dx addw %bx, %dx movw %dx, %es popw %bx subw %si, %cx jnz .ReadLBA popw %es ret DiskError: /* Display disk error message and reboot */ movw $.MsgDiskError, %si call Print jmp Reboot FsError: /* Display FS error message and reboot */ movw $.MsgFsError, %si call Print jmp Reboot Print: /* Simple routine to print messages */ lodsb orb %al, %al jz .DonePrint movb $0x0E, %ah movw $0x07, %bx int $0x10 jmp Print .DonePrint: retw Reboot: /* Display a message, wait for a key press and reboot */ movw $.MsgAnyKey, %si call Print xorw %ax, %ax int $0x16 int $0x19 .MsgAnyKey: .ascii "Press any key to restart...\r\n\0" .MsgDiskError: .ascii "Disk error!\r\n\0" .MsgFsError: .ascii "File system error!\r\n\0" /* Fill the rest of the VBR with zeros and add VBR signature at the end */ .fill (510 - (. - Start)), 1, 0 .word 0xAA55 StartExtraCode: /* Load XTLDR file from disk */ call LoadStage2 /* Enable A20 gate */ call EnableA20 /* Call architecture specific initialization code */ call InitializeCpu /* Jump to Stage2 */ call RunStage2 Clear8042: /* Clear 8042 PS/2 buffer */ nop nop nop nop inb $0x64, %al cmpb $0xff, %al je .Clear8042_Done testb $0x02, %al jnz Clear8042 .Clear8042_Done: ret EnableA20: /* Enable A20 gate */ pushaw call Clear8042 movb $0xD1, %al outb %al, $0x64 call Clear8042 movb $0xDF, %al outb %al, $0x60 call Clear8042 movb $0xFF, %al outb %al, $0x64 call Clear8042 popaw ret FindFatEntry: /* Find a file or directory in the FAT table */ pushw %bx pushw %cx pushw %dx pushw %si pushw %di .FindFatCluster: /* Find FAT32 cluster holding the entry */ cmp $0x0FFFFFF8, %eax jae .FindEntryFail pushl %eax movw $0x0200, %bx movw %bx, %es call ReadCluster popl %eax movb SectorsPerCluster - Start(%bp), %cl shlw $0x04, %cx xorw %di, %di .FindEntryLoop: /* Find the entry */ movb %es:(%di), %al cmpb $0x00, %al je .FindEntryFail cmpb $0xE5, %al je .FindSkipEntry movb %es:0x0B(%di), %ah cmpb $0x0F, %ah je .FindSkipEntry pushw %di pushw %si pushw %cx movw $0x0B, %cx repe cmpsb popw %cx popw %si popw %di jnz .FindSkipEntry movw %es:0x1A(%di), %ax movw %es:0x14(%di), %dx shll $0x10, %edx orl %edx, %eax clc jmp .FindEntryDone .FindSkipEntry: /* Skip to the next entry */ addw $0x20, %di decw %cx jnz .FindEntryLoop call GetFatEntry jmp .FindFatCluster .FindEntryFail: /* Error, file/directory not found */ stc .FindEntryDone: /* Clean up the stack */ popw %di popw %si popw %dx popw %cx popw %bx ret GetFatEntry: /* Get FAT32 sector and offset from FAT table */ shll $0x02, %eax movl %eax, %ecx xorl %edx, %edx movzwl BytesPerSector - Start(%bp), %ebx pushl %ebx divl %ebx movzwl ReservedSectors - Start(%bp), %ebx addl %ebx, %eax movl HiddenSectors - Start(%bp), %ebx addl %ebx, %eax popl %ebx decl %ebx andl %ebx, %ecx movzwl ExtendedFlags - Start(%bp), %ebx andw $0x0F, %bx jz LoadFatSector cmpb FatCopies - Start(%bp), %bl jae FsError pushl %eax movl BigSectorsPerFat - Start(%bp), %eax mull %ebx popl %edx addl %edx, %eax LoadFatSector: /* Load FAT32 sector from disk */ pushl %ecx movw $0x9000, %bx movw %bx, %es cmpl %esi, %eax je .LoadFatSectorDone movl %eax, %esi xorw %bx, %bx movw $0x01, %cx call ReadSectors .LoadFatSectorDone: /* Clean up the stack */ popl %ecx movl %es:(%ecx), %eax andl $0x0FFFFFFF, %eax ret LoadStage2: /* Load Stage2 executable, first find file in the path */ movl $0xFFFFFFFF, %esi pushl %esi movl 0x7C2C, %eax movw $.EfiDirName, %si call FindFatEntry jc Stage2NotLoaded movw $.BootDirName, %si call FindFatEntry jc Stage2NotLoaded movw $.Stage2FileName, %si call FindFatEntry jc Stage2NotLoaded popl %esi /* Load XTLDR file from disk */ cmpl $0x02, %eax jb FileNotFound cmpl $0x0FFFFFF8, %eax jae FileNotFound movw $(0xF800 / 16), %bx movw %bx, %es .LoadStage2Loop: /* Load file data from disk */ pushl %eax xorw %bx, %bx pushw %es call ReadCluster popw %es xorw %bx, %bx movb SectorsPerCluster - Start(%bp), %bl shlw $0x05, %bx movw %es, %ax addw %bx, %ax movw %ax, %es popl %eax pushw %es call GetFatEntry popw %es cmpl $0x0FFFFFF8, %eax jb .LoadStage2Loop ret ParseExecutableHeader: /* Parse Stage2 PE/COFF executable header */ pushw %es movw $(0xF800 / 16), %ax movw %ax, %es movl %es:60, %eax addl $(4 + 20), %eax movl %es:16(%eax), %eax addl $0xF800, %eax popw %es ret ReadCluster: /* Read FAT32 cluster from disk */ decl %eax decl %eax xorl %edx, %edx movzbl SectorsPerCluster - Start(%bp), %ebx mull %ebx pushl %eax xorl %edx, %edx movzbl FatCopies - Start(%bp), %eax mull BigSectorsPerFat - Start(%bp) movzwl ReservedSectors - Start(%bp), %ebx addl %ebx, %eax addl HiddenSectors - Start(%bp), %eax popl %ebx addl %ebx, %eax xorw %bx, %bx movzbw SectorsPerCluster - Start(%bp), %cx call ReadSectors ret /* Include architecture specific code */ .include ARCH_ESP_SOURCE CpuUnsupported: /* Display CPU unsupported message and reboot */ popal movw $.MsgCpuUnsupported, %si call Print jmp Reboot FileNotFound: /* Display XTLDR not found message and reboot */ movw $.MsgXtLdrNotFound, %si call Print jmp Reboot Stage2NotLoaded: /* Clean up the stack and display XTLDR not found message and reboot */ popl %esi jmp FileNotFound .BootDirName: /* Boot directory name */ .ascii "BOOT " .EfiDirName: /* EFI directory name */ .ascii "EFI " .MsgCpuUnsupported: .ascii "CPU not supported!\r\n\0" .MsgXtLdrNotFound: .ascii "XTLDR Stage2 not found!\r\n\0" /* Fill the rest of the extra VBR with zeros and add signature */ .fill (2043 - (. - Start)), 1, 0 .ascii "XTLDR" ================================================ FILE: boot/bootsect/i686/cpu.S ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: boot/bootsect/i686/cpu.S * DESCRIPTION: Low-level support for CPU initialization * DEVELOPERS: Aiken Harris */ BuildPageMap: /* Generate page map for first 16MB of memory */ pushaw pushw %es cld movw $(0x1000 >> 0x04), %ax movw %ax, %es xorw %di, %di movl $(0x2000 | 0x03), %eax stosl movl $(0x3000 | 0x03), %eax stosl movl $(0x4000 | 0x03), %eax stosl movl $(0x5000 | 0x03), %eax stosl xorl %eax, %eax movw $(1024 - 4), %cx rep stosl movl $0x00000003, %eax movl $4, %edx movw $(0x2000 >> 0x04), %bx .BuildPageMapLoop: /* Identity map 1024 pages of 4KB */ movw %bx, %es xorw %di, %di pushl %edx movw $1024, %cx .FillPageMapTable: /* Fill the page table */ movl %eax, %es:(%di) addl $4096, %eax addw $0x04, %di loop .FillPageMapTable popl %edx addw $(0x1000 >> 0x04), %bx decl %edx jnz .BuildPageMapLoop popw %es popaw ret InitializeCpu: /* Check if CPU supports CPUID */ pushal pushfl popl %eax movl %eax, %ebx xorl $0x00200000, %eax pushl %eax popfl pushfl popl %eax cmpl %ebx, %eax je CpuUnsupported popal call LoadGdt ret LoadGdt: /* Load Global Descriptor Table */ lgdt .GdtPointer ret RunStage2: /* Switch to protected mode and pass control to Stage 2 */ call BuildPageMap call ParseExecutableHeader pushl %eax cli movl %cr0, %eax orl $0x01, %eax movl %eax, %cr0 ljmp $0x08, $.Stage2ProtectedMode .code32 .Stage2ProtectedMode: /* Set segments and stack, then jump to Stage 2 */ movw $0x10, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss xorw %ax, %ax movw %ax, %fs movw %ax, %gs popl %eax xorl %ebx, %ebx xorl %ecx, %ecx xorl %edx, %edx xorl %esi, %esi xorl %edi, %edi xorl %ebp, %ebp movl $0x1000, %ebx movl %ebx, %cr3 movl %cr0, %ebx orl $0x80000000, %ebx movl %ebx, %cr0 jmp *%eax .code16 .GdtDescriptor: /* Global Descriptor Table */ .quad 0x0000000000000000 .quad 0x00CF9A000000FFFF .quad 0x00CF92000000FFFF .quad 0x00009E000000FFFF .quad 0x000092000000FFFF .GdtPointer: /* Pointer to Global Descriptor Table */ .word .GdtPointer - .GdtDescriptor - 1 .long .GdtDescriptor .Stage2FileName: /* Name of Stage 2 executable file */ .ascii "BOOTIA32EFI" ================================================ FILE: boot/bootsect/mbrboot.S ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: boot/bootsect/amd64/mbrboot.S * DESCRIPTION: XT Boot Loader MBR boot code * DEVELOPERS: Rafal Kupiec * Aiken Harris */ .text .code16 .global Start Start: /* Set segments and stack */ cli cld xorw %ax, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss movw $0x7C00, %bp leaw -16(%bp), %sp sti /* Relocate MBR to 1FE0:7C00 */ movw $0x1FE0, %ax movw %ax, %es movw %bp, %si movw %bp, %di movw $256, %cx rep movsw /* Jump to the relocated MBR code */ jmp $0x1FE0, $RealStart RealStart: /* Set segments */ movw %ax, %ds movw %ax, %es movw %ax, %ss /* Print welcome message */ leaw .MsgXtosBoot, %si call Print /* Get BIOS boot drive and partition table offset */ lea 0x1BE(%bp), %si movb %dl, .BootDrive xorw %cx, %cx FindActivePartition: /* Look for active partition */ movb (%si), %al cmpb $0x80, %al je PartitionFound addw $16, %si incw %cx cmpw $4, %cx jne FindActivePartition jmp PartitionNotFound PartitionFound: /* Save LBA start */ movl 8(%si), %eax movl %eax, .LbaStart /* Prepare Disk Address Packet (DAP) */ lea .Dap, %si movb $0x10, 0(%si) movb $0x00, 1(%si) movw $1, 2(%si) movw $0x7C00, 4(%si) movw $0x0000, 6(%si) movl .LbaStart, %eax movl %eax, 8(%si) /* Read Volume Boot Record (VBR) */ movb $0x42, %ah movb .BootDrive, %dl int $0x13 jc VbrReadFail /* Verify VBR signature */ cmpw $0xAA55, (0x7C00 + 0x01FE) jne InvalidSignature /* Jump to the VBR code */ jmp $0x0000, $0x7C00 InvalidSignature: /* Invalid signature error */ leaw .MsgInvalidSignature, %si call Print jmp HaltSystem PartitionNotFound: /* Active partition not found error */ leaw .MsgPartitionNotFound, %si call Print jmp HaltSystem VbrReadFail: /* VBR read failed error */ leaw .MsgVbrReadFail, %si call Print jmp HaltSystem HaltSystem: /* Disable interrupts and stop the CPU */ cli hlt jmp HaltSystem Print: /* Simple routine to print messages */ lodsb orb %al, %al jz DonePrint movb $0x0E, %ah movw $0x07, %bx int $0x10 jmp Print DonePrint: retw .BootDrive: /* Storage for the boot drive number */ .byte 0 .Dap: /* Storage for the Disk Address Packet (DAP) */ .fill 16, 1, 0 .LbaStart: /* Storage for the LBA start */ .long 0 .MsgInvalidSignature: .asciz "Invalid partition signature!" .MsgPartitionNotFound: .asciz "Bootable partition not found!" .MsgVbrReadFail: .asciz "VBR read failed!" .MsgXtosBoot: .asciz "Starting XTOS boot loader...\r\n" /* Fill the rest of the MBR with zeros and add MBR signature at the end */ .fill (510 - (. - Start)), 1, 0 .word 0xAA55 ================================================ FILE: boot/xtldr/CMakeLists.txt ================================================ # XT Boot Loader PROJECT(XTLDR) # Build XTLDR modules add_subdirectory(modules) # Specify include directories include_directories( ${EXECTOS_SOURCE_DIR}/sdk/xtdk ${XTLDR_SOURCE_DIR}/includes) # Specify list of library source code files list(APPEND LIBXTLDR_SOURCE ${XTLDR_SOURCE_DIR}/library/modproto.cc) # Specify list of source code files list(APPEND XTLDR_SOURCE ${XTLDR_SOURCE_DIR}/arch/${ARCH}/memory.cc ${XTLDR_SOURCE_DIR}/biosutil.cc ${XTLDR_SOURCE_DIR}/bootutil.cc ${XTLDR_SOURCE_DIR}/config.cc ${XTLDR_SOURCE_DIR}/console.cc ${XTLDR_SOURCE_DIR}/data.cc ${XTLDR_SOURCE_DIR}/debug.cc ${XTLDR_SOURCE_DIR}/efiutils.cc ${XTLDR_SOURCE_DIR}/memory.cc ${XTLDR_SOURCE_DIR}/protocol.cc ${XTLDR_SOURCE_DIR}/shell.cc ${XTLDR_SOURCE_DIR}/textui.cc ${XTLDR_SOURCE_DIR}/volume.cc ${XTLDR_SOURCE_DIR}/xtldr.cc) # Link static XTLDR library add_library(libxtldr ${LIBXTLDR_SOURCE}) # Link bootloader executable add_executable(xtldr ${XTLDR_SOURCE}) # Add linker libraries target_link_libraries(xtldr libxtos) # Add linker options target_link_options(xtldr PRIVATE /ALIGN:512) # Set proper binary name and install target if(ARCH STREQUAL "i686") set(BINARY_NAME "bootia32") elseif(ARCH STREQUAL "amd64") set(BINARY_NAME "bootx64") endif() set_target_properties(xtldr PROPERTIES OUTPUT_NAME ${BINARY_NAME} SUFFIX .efi) set_install_target(xtldr efi/boot) # Set loader entrypoint and subsystem set_entrypoint(xtldr "BlStartXtLoader") set_imagebase(xtldr ${BASEADDRESS_XTLDR}) set_linker_map(xtldr TRUE) set_subsystem(xtldr efi_application) ================================================ FILE: boot/xtldr/README.md ================================================ ## XT Boot Loader (XTLDR) The XTLDR, or XTOS Boot Loader, is an EFI (Extensible Firmware Interface) boot loader specifically designed for XTOS. As an EFI boot loader, XTLDR operates exclusively with EFI-based hardware and is not compatible with non-EFI systems, like old and deprecated BIOS. One of the notable features of XTLDR is its modular design. The boot loader is divided into different modules, with only the essential core being loaded during the boot process. This modular approach allows for a more efficient and streamlined boot experience, as only the necessary functionality is loaded, reducing the boot time and system resource usage. XTLDR includes various modules that provide specific functionalities required for the boot process. For example, there is a module dedicated to supporting the XTOS boot protocol, which is the specific protocol used by XTOS for loading and executing the OS kernel. Additionally, there is a module for handling PE/COFF (Portable Executable) binaries, which is a commonly used format of executable files used by the XTOS. ================================================ FILE: boot/xtldr/arch/amd64/memory.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/arch/amd64/memory.cc * DESCRIPTION: XT Boot Loader AMD64 specific memory management * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Maps boot loader related code and builds page map. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @param SelfMapAddress * Supplies a virtual address of the page tables. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR SelfMapAddress) { PLIST_ENTRY ModulesList, ModulesListEntry; PXTBL_MODULE_INFO ModuleInfo; EFI_PHYSICAL_ADDRESS Address; ULONGLONG LoaderSize; EFI_STATUS Status; PVOID LoaderBase; /* Allocate pages for the Page Map */ Status = AllocatePages(AllocateAnyPages, 1, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Add new memory mapping for the page map itself */ Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ return Status; } /* Assign and zero-fill memory used by page mappings */ PageMap->PtePointer = (PVOID)(UINT_PTR)Address; RTL::Memory::ZeroMemory(PageMap->PtePointer, EFI_PAGE_SIZE); /* Add page mapping itself to memory mapping */ Status = Memory::SelfMapPml(PageMap, SelfMapAddress); if(Status != STATUS_EFI_SUCCESS) { /* PML mapping failed */ return Status; } /* Map the trampoline code area */ Status = MapVirtualMemory(PageMap, MM_TRAMPOLINE_ADDRESS, MM_TRAMPOLINE_ADDRESS, 1, LoaderFirmwareTemporary); if(Status != STATUS_EFI_SUCCESS) { /* Mapping trampoline code failed */ return Status; } /* Get list of XTLDR modules */ ModulesList = Protocol::GetModulesList(); ModulesListEntry = ModulesList->Flink; while(ModulesListEntry != ModulesList) { /* Get module info */ ModuleInfo = CONTAIN_RECORD(ModulesListEntry, XTBL_MODULE_INFO, Flink); /* Map module code */ Status = MapVirtualMemory(PageMap, (ULONGLONG)ModuleInfo->ModuleBase, (ULONGLONG)ModuleInfo->ModuleBase, EFI_SIZE_TO_PAGES(ModuleInfo->ModuleSize), LoaderFirmwareTemporary); /* Check if mapping succeeded */ if(Status != STATUS_EFI_SUCCESS) { /* Mapping module code failed */ return Status; } /* Get next module */ ModulesListEntry = ModulesListEntry->Flink; } /* Get boot loader image information */ XtLoader::GetLoaderImageInformation(&LoaderBase, &LoaderSize); /* Make sure boot loader image base and size are set */ if(LoaderBase && LoaderSize) { /* Map boot loader code as well */ Status = MapVirtualMemory(PageMap, (ULONGLONG)LoaderBase, (ULONGLONG)LoaderBase, EFI_SIZE_TO_PAGES(LoaderSize), LoaderFirmwareTemporary); if(Status != STATUS_EFI_SUCCESS) { /* Mapping boot loader code failed */ return Status; } } else { /* Boot loader image information re not available */ return STATUS_EFI_PROTOCOL_ERROR; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Iterates through the memory map and physically maps all virtual addresses to page tables. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::CommitPageMap(IN PXTBL_PAGE_MAPPING PageMap) { PXTBL_MEMORY_MAPPING Mapping; PLIST_ENTRY ListEntry; EFI_STATUS Status; /* Iterate through and map all the mappings*/ Debug::Print(L"Mapping and dumping EFI memory:\n"); ListEntry = PageMap->MemoryMap.Flink; while(ListEntry != &PageMap->MemoryMap) { /* Take mapping from the list */ Mapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry); /* Check if virtual address is set */ if(Mapping->VirtualAddress) { /* Dump memory mapping */ Debug::Print(L" Type=%02lu, PhysicalBase=%.16P, VirtualBase=%.16P, Pages=%llu\n", Mapping->MemoryType, Mapping->PhysicalAddress, Mapping->VirtualAddress, Mapping->NumberOfPages); /* Map memory */ Status = MapPage(PageMap, (UINT_PTR)Mapping->VirtualAddress, (UINT_PTR)Mapping->PhysicalAddress, Mapping->NumberOfPages); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failed */ return Status; } } /* Take next element */ ListEntry = ListEntry->Flink; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Returns next level of the Page Table. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @param PageTable * Supplies a pointer to the current Page Table. * * @param Entry * Supplies an index of the current Page Table entry. * * @param NextPageTable * Supplies a pointer to the memory area where the next Page Table level is returned. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, IN PVOID PageTable, IN SIZE_T Entry, OUT PVOID *NextPageTable) { EFI_PHYSICAL_ADDRESS Address; ULONGLONG PmlPointer = 0; PHARDWARE_PTE PmlTable; EFI_STATUS Status; PmlTable = (PHARDWARE_PTE)PageTable; /* Check if this is a valid table */ if(PmlTable[Entry].Valid) { /* Get PML pointer */ PmlPointer = PmlTable[Entry].PageFrameNumber; PmlPointer <<= EFI_PAGE_SHIFT; } else { /* Allocate pages for new PML entry */ Status = AllocatePages(AllocateAnyPages, 1, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Add new memory mapping */ Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ return Status; } /* Fill allocated memory with zeros */ RTL::Memory::ZeroMemory((PVOID)(ULONGLONG)Address, EFI_PAGE_SIZE); /* Set paging entry settings */ PmlTable[Entry].PageFrameNumber = Address / EFI_PAGE_SIZE; PmlTable[Entry].Valid = 1; PmlTable[Entry].Writable = 1; PmlPointer = (ULONGLONG)Address; } /* Set next Page Map Level (PML) */ *NextPageTable = (PVOID)(ULONGLONG)PmlPointer; /* Return success */ return STATUS_EFI_SUCCESS; } /** * Does the actual virtual memory mapping. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @param VirtualAddress * Supplies a virtual address of the mapping. * * @param PhysicalAddress * Supplies a physical address of the mapping. * * @param NumberOfPages * Supplies a number of the pages of the mapping. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::MapPage(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages) { PVOID Pml1, Pml2, Pml3, Pml4, Pml5; SIZE_T Pml1Entry, Pml2Entry, Pml3Entry, Pml4Entry, Pml5Entry; PHARDWARE_PTE PmlTable; SIZE_T PageFrameNumber; EFI_STATUS Status; /* Set the Page Frame Number (PFN) */ PageFrameNumber = PhysicalAddress >> EFI_PAGE_SHIFT; /* Do the recursive mapping */ while(NumberOfPages > 0) { /* Calculate the indices in the various Page Tables from the virtual address */ Pml5Entry = (VirtualAddress & ((ULONGLONG)0x1FF << MM_P5I_SHIFT)) >> MM_P5I_SHIFT; Pml4Entry = (VirtualAddress & ((ULONGLONG)0x1FF << MM_PXI_SHIFT)) >> MM_PXI_SHIFT; Pml3Entry = (VirtualAddress & ((ULONGLONG)0x1FF << MM_PPI_SHIFT)) >> MM_PPI_SHIFT; Pml2Entry = (VirtualAddress & ((ULONGLONG)0x1FF << MM_PDI_SHIFT)) >> MM_PDI_SHIFT; Pml1Entry = (VirtualAddress & ((ULONGLONG)0x1FF << MM_PTI_SHIFT)) >> MM_PTI_SHIFT; /* Check page map level */ if(PageMap->PageMapLevel == 5) { /* Five level Page Map */ Pml5 = PageMap->PtePointer; /* Get PML4 */ Status = GetNextPageTable(PageMap, Pml5, Pml5Entry, &Pml4); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ return Status; } } else { /* Four level Page Map */ Pml4 = PageMap->PtePointer; } /* Get PML3 */ Status = GetNextPageTable(PageMap, Pml4, Pml4Entry, &Pml3); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ return Status; } /* Get PML 2 */ Status = GetNextPageTable(PageMap, Pml3, Pml3Entry, &Pml2); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ return Status; } /* Get PML1 */ Status = GetNextPageTable(PageMap, Pml2, Pml2Entry, &Pml1); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ return Status; } /* Set paging entry settings */ PmlTable = (PHARDWARE_PTE)Pml1; RTL::Memory::ZeroMemory(&PmlTable[Pml1Entry], sizeof(HARDWARE_PTE)); PmlTable[Pml1Entry].PageFrameNumber = PageFrameNumber; PmlTable[Pml1Entry].Valid = 1; PmlTable[Pml1Entry].Writable = 1; /* Take next virtual address and PFN */ VirtualAddress += EFI_PAGE_SIZE; PageFrameNumber++; /* Decrease number of pages left */ NumberOfPages--; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Creates a recursive self mapping for all PML levels. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @param SelfMapAddress * Supplies a virtual address of the page tables. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::SelfMapPml(IN PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR SelfMapAddress) { PHARDWARE_PTE PmlBase; ULONGLONG PmlIndex; /* Initialize PML base pointer */ PmlBase = (PHARDWARE_PTE)PageMap->PtePointer; /* Check page map level */ if(PageMap->PageMapLevel == 5) { /* Calculate PML index based on provided self map address for PML5 */ PmlIndex = (SelfMapAddress >> MM_P5I_SHIFT) & 0x1FF; } else { /* Calculate PML index based on provided self map address for PML4 */ PmlIndex = (SelfMapAddress >> MM_PXI_SHIFT) & 0x1FF; } /* Add self-mapping */ RTL::Memory::ZeroMemory(&PmlBase[PmlIndex], sizeof(HARDWARE_PTE)); PmlBase[PmlIndex].PageFrameNumber = (UINT_PTR)PageMap->PtePointer / EFI_PAGE_SIZE; PmlBase[PmlIndex].Valid = 1; PmlBase[PmlIndex].Writable = 1; /* Return success */ return STATUS_EFI_SUCCESS; } ================================================ FILE: boot/xtldr/arch/i686/memory.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/arch/i686/memory.cc * DESCRIPTION: XT Boot Loader i686 specific memory management * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Maps boot loader related code and builds page map. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR SelfMapAddress) { EFI_PHYSICAL_ADDRESS Address, DirectoryAddress; PLIST_ENTRY ModulesList, ModulesListEntry; PXTBL_MODULE_INFO ModuleInfo; ULONGLONG LoaderSize; EFI_STATUS Status; PVOID LoaderBase; ULONG Index; /* Check the page map level to determine which paging structure to create */ if(PageMap->PageMapLevel == 3) { /* Allocate a page for the 3-level page map structure (PAE enabled) */ Status = AllocatePages(AllocateAnyPages, 1, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failed, cannot proceed with page map creation */ return Status; } /* Add new memory mapping for the page map itself */ Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ return Status; } /* Assign the allocated page to the page map and zero it out */ PageMap->PtePointer = (PVOID)(UINT_PTR)Address; RTL::Memory::ZeroMemory(PageMap->PtePointer, EFI_PAGE_SIZE); /* Allocate 4 pages for the Page Directories (PDs) */ Status = AllocatePages(AllocateAnyPages, 4, &DirectoryAddress); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failed, cannot proceed with page map creation */ return Status; } /* Add new memory mapping for the Page Directories (PDs) */ Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, DirectoryAddress, 4, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ return Status; } /* Zero-fill the allocated memory for the Page Directories */ RTL::Memory::ZeroMemory((PVOID)DirectoryAddress, EFI_PAGE_SIZE * 4); /* Fill the PDPT with pointers to the Page Directories */ for(Index = 0; Index < 4; Index++) { RTL::Memory::ZeroMemory(&((PHARDWARE_MODERN_PTE)PageMap->PtePointer)[Index], sizeof(HARDWARE_MODERN_PTE)); ((PHARDWARE_MODERN_PTE)PageMap->PtePointer)[Index].PageFrameNumber = DirectoryAddress / EFI_PAGE_SIZE; ((PHARDWARE_MODERN_PTE)PageMap->PtePointer)[Index].Valid = 1; DirectoryAddress += EFI_PAGE_SIZE; } } else { /* Allocate a page for the 2-level page map structure (PAE disabled) */ Status = AllocatePages(AllocateAnyPages, 1, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failed, cannot proceed with page map creation */ return Status; } /* Add new memory mapping for the page map itself */ Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ return Status; } /* Assign the allocated page to the page map and zero it out */ PageMap->PtePointer = (PVOID)(UINT_PTR)Address; RTL::Memory::ZeroMemory(PageMap->PtePointer, EFI_PAGE_SIZE); } /* Add page mapping itself to memory mapping */ Status = SelfMapPml(PageMap, SelfMapAddress); if(Status != STATUS_EFI_SUCCESS) { /* PML mapping failed */ return Status; } /* Map the trampoline code area */ Status = MapVirtualMemory(PageMap, MM_TRAMPOLINE_ADDRESS, MM_TRAMPOLINE_ADDRESS, 1, LoaderFirmwareTemporary); if(Status != STATUS_EFI_SUCCESS) { /* Mapping trampoline code failed */ return Status; } /* Get list of XTLDR modules */ ModulesList = Protocol::GetModulesList(); ModulesListEntry = ModulesList->Flink; while(ModulesListEntry != ModulesList) { /* Get module info */ ModuleInfo = CONTAIN_RECORD(ModulesListEntry, XTBL_MODULE_INFO, Flink); /* Map module code */ Status = MapVirtualMemory(PageMap, (ULONGLONG)ModuleInfo->ModuleBase, (ULONGLONG)ModuleInfo->ModuleBase, EFI_SIZE_TO_PAGES(ModuleInfo->ModuleSize), LoaderFirmwareTemporary); /* Check if mapping succeeded */ if(Status != STATUS_EFI_SUCCESS) { /* Mapping module code failed */ return Status; } /* Get next module */ ModulesListEntry = ModulesListEntry->Flink; } /* Get boot loader image information */ XtLoader::GetLoaderImageInformation(&LoaderBase, &LoaderSize); /* Make sure boot loader image base and size are set */ if(LoaderBase && LoaderSize) { /* Map boot loader code as well */ Status = MapVirtualMemory(PageMap, (ULONGLONG)LoaderBase, (ULONGLONG)LoaderBase, EFI_SIZE_TO_PAGES(LoaderSize), LoaderFirmwareTemporary); if(Status != STATUS_EFI_SUCCESS) { /* Mapping boot loader code failed */ return Status; } } else { /* Boot loader image information re not available */ return STATUS_EFI_PROTOCOL_ERROR; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Iterates through the memory map and physically maps all virtual addresses to page tables. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::CommitPageMap(IN PXTBL_PAGE_MAPPING PageMap) { PXTBL_MEMORY_MAPPING Mapping; PLIST_ENTRY ListEntry; EFI_STATUS Status; /* Iterate through and map all the mappings*/ Debug::Print(L"Mapping and dumping EFI memory:\n"); ListEntry = PageMap->MemoryMap.Flink; while(ListEntry != &PageMap->MemoryMap) { /* Take mapping from the list */ Mapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry); /* Check if virtual address is set */ if(Mapping->VirtualAddress) { /* Dump memory mapping */ Debug::Print(L" Type=%02lu, PhysicalBase=0x%.8llX, VirtualBase=0x%.8llX, Pages=%llu\n", Mapping->MemoryType, Mapping->PhysicalAddress, Mapping->VirtualAddress, Mapping->NumberOfPages); /* Map memory */ Status = MapPage(PageMap, (UINT_PTR)Mapping->VirtualAddress, (UINT_PTR)Mapping->PhysicalAddress, Mapping->NumberOfPages); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failed */ return Status; } } /* Take next element */ ListEntry = ListEntry->Flink; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Returns next level of the Page Table. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @param PageTable * Supplies a pointer to the current Page Table. * * @param Entry * Supplies an index of the current Page Table entry. * * @param NextPageTable * Supplies a pointer to the memory area where the next Page Table level is returned. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, IN PVOID PageTable, IN SIZE_T Entry, OUT PVOID *NextPageTable) { EFI_PHYSICAL_ADDRESS Address; ULONGLONG PmlPointer = 0; EFI_STATUS Status; PHARDWARE_LEGACY_PTE LegacyPmlTable; PHARDWARE_MODERN_PTE PmlTable; BOOLEAN ValidPte = FALSE; /* Check page map level to determine PTE size */ if(PageMap->PageMapLevel >= 3) { /* 64-bit PTE for PML3 (PAE enabled) */ PmlTable = (PHARDWARE_MODERN_PTE)PageTable; if(PmlTable[Entry].Valid) { /* Get page frame number from page table entry */ PmlPointer = PmlTable[Entry].PageFrameNumber; ValidPte = TRUE; } } else { /* 32-bit PTE for PML2 (PAE disabled) */ LegacyPmlTable = (PHARDWARE_LEGACY_PTE)PageTable; if(LegacyPmlTable[Entry].Valid) { /* Get page frame number from page table entry */ PmlPointer = LegacyPmlTable[Entry].PageFrameNumber; ValidPte = TRUE; } } /* Check if page table entry is valid */ if(ValidPte) { /* Calculate the base address of the next page table */ PmlPointer <<= EFI_PAGE_SHIFT; } else { /* Allocate pages for new PML entry */ Status = AllocatePages(AllocateAnyPages, 1, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Add new memory mapping */ Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ return Status; } /* Fill allocated memory with zeros */ RTL::Memory::ZeroMemory((PVOID)(ULONGLONG)Address, EFI_PAGE_SIZE); /* Set paging entry settings based on level */ if(PageMap->PageMapLevel >= 3) { /* 64-bit PTE for PML3 (PAE enabled) */ PmlTable = (PHARDWARE_MODERN_PTE)PageTable; PmlTable[Entry].PageFrameNumber = Address / EFI_PAGE_SIZE; PmlTable[Entry].Valid = 1; PmlTable[Entry].Writable = 1; } else { /* 32-bit PTE for PML2 (PAE disabled) */ LegacyPmlTable = (PHARDWARE_LEGACY_PTE)PageTable; LegacyPmlTable[Entry].PageFrameNumber = (UINT32)(Address / EFI_PAGE_SIZE); LegacyPmlTable[Entry].Valid = 1; LegacyPmlTable[Entry].Writable = 1; } /* Return the address of the new page table */ PmlPointer = (ULONGLONG)Address; } /* Set next Page Map Level (PML) */ *NextPageTable = (PVOID)(ULONGLONG)PmlPointer; /* Return success */ return STATUS_EFI_SUCCESS; } /** * Does the actual virtual memory mapping. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @param VirtualAddress * Supplies a virtual address of the mapping. * * @param PhysicalAddress * Supplies a physical address of the mapping. * * @param NumberOfPages * Supplies a number of the pages of the mapping. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::MapPage(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages) { ULONGLONG PageFrameNumber; PVOID Pml1, Pml2, Pml3; SIZE_T Pml1Entry, Pml2Entry, Pml3Entry; PHARDWARE_LEGACY_PTE LegacyPmlTable; PHARDWARE_MODERN_PTE PmlTable; EFI_STATUS Status; /* Set the Page Frame Number (PFN) */ PageFrameNumber = PhysicalAddress >> EFI_PAGE_SHIFT; /* Map all requested pages */ while(NumberOfPages > 0) { /* Check the paging mode to use the correct page table structure */ if(PageMap->PageMapLevel == 3) { /* Calculate the indices for PAE page tables */ Pml3Entry = (VirtualAddress >> 30) & 0x3; Pml2Entry = (VirtualAddress >> 21) & 0x1FF; Pml1Entry = (VirtualAddress >> 12) & 0x1FF; /* Get Page Directory Pointer Table (PML3) */ Pml3 = PageMap->PtePointer; /* Get Page Directory (PML2) */ Status = GetNextPageTable(PageMap, Pml3, Pml3Entry, &Pml2); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get the Page Table, abort mapping */ return Status; } /* Get Page Table (PML1) */ Status = GetNextPageTable(PageMap, Pml2, Pml2Entry, &Pml1); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get the Page Table, abort mapping */ return Status; } /* Set the 64-bit PTE entry */ PmlTable = (PHARDWARE_MODERN_PTE)Pml1; RTL::Memory::ZeroMemory(&PmlTable[Pml1Entry], sizeof(HARDWARE_MODERN_PTE)); PmlTable[Pml1Entry].PageFrameNumber = PageFrameNumber; PmlTable[Pml1Entry].Valid = 1; PmlTable[Pml1Entry].Writable = 1; } else { /* Calculate the indices for non-PAE page tables */ Pml2Entry = (VirtualAddress >> 22) & 0x3FF; Pml1Entry = (VirtualAddress >> 12) & 0x3FF; /* Get Page Directory (PML2) */ Pml2 = PageMap->PtePointer; /* Get Page Table (PML1) */ Status = GetNextPageTable(PageMap, Pml2, Pml2Entry, &Pml1); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get the Page Table, abort mapping */ return Status; } /* Set the 32-bit PTE entry */ LegacyPmlTable = (PHARDWARE_LEGACY_PTE)Pml1; RTL::Memory::ZeroMemory(&LegacyPmlTable[Pml1Entry], sizeof(HARDWARE_LEGACY_PTE)); LegacyPmlTable[Pml1Entry].PageFrameNumber = (UINT32)PageFrameNumber; LegacyPmlTable[Pml1Entry].Valid = 1; LegacyPmlTable[Pml1Entry].Writable = 1; } /* Take next virtual address and PFN */ VirtualAddress += EFI_PAGE_SIZE; PageFrameNumber++; /* Decrease number of pages left */ NumberOfPages--; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Creates a recursive self mapping for all PML levels. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @param SelfMapAddress * Supplies a virtual address of the page tables. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::SelfMapPml(IN PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR SelfMapAddress) { PHARDWARE_LEGACY_PTE LegacyPml; PHARDWARE_MODERN_PTE Pml; ULONGLONG PmlIndex; ULONG Index; /* Check page map level */ if(PageMap->PageMapLevel == 3) { /* Calculate PML index based on provided self map address */ PmlIndex = (SelfMapAddress >> MM_PDI_SHIFT) & 0x1FF; /* Get Page Directory */ Pml = (PHARDWARE_MODERN_PTE)(((PHARDWARE_MODERN_PTE)PageMap->PtePointer)[SelfMapAddress >> MM_PPI_SHIFT].PageFrameNumber * EFI_PAGE_SIZE); /* Add self-mapping for PML3 (PAE enabled) */ for(Index = 0; Index < 4; Index++) { RTL::Memory::ZeroMemory(&Pml[PmlIndex + Index], sizeof(HARDWARE_MODERN_PTE)); Pml[PmlIndex + Index].PageFrameNumber = ((PHARDWARE_MODERN_PTE)PageMap->PtePointer)[Index].PageFrameNumber; Pml[PmlIndex + Index].Valid = 1; Pml[PmlIndex + Index].Writable = 1; } } else { LegacyPml = (PHARDWARE_LEGACY_PTE)PageMap->PtePointer; /* Calculate PML index based on provided self map address */ PmlIndex = (SelfMapAddress >> MM_PDI_LEGACY_SHIFT); /* Add self-mapping for PML2 (PAE disabled) */ RTL::Memory::ZeroMemory(&LegacyPml[PmlIndex], sizeof(HARDWARE_LEGACY_PTE)); LegacyPml[PmlIndex].PageFrameNumber = (UINT_PTR)PageMap->PtePointer / EFI_PAGE_SIZE; LegacyPml[PmlIndex].Valid = 1; LegacyPml[PmlIndex].Writable = 1; } /* Return success */ return STATUS_EFI_SUCCESS; } ================================================ FILE: boot/xtldr/biosutil.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/biosutil.cc * DESCRIPTION: Legacy BIOS support * DEVELOPERS: Aiken Harris */ #include /** * Clears the entire screen and moves the cursor to the top-left corner. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID BiosUtils::ClearScreen() { VOLATILE PUSHORT VgaBuffer = (PUSHORT)0xB8000; USHORT Blank; UINT Index; /* Set blank character */ Blank = (0x0F << 8) | L' '; /* Fill the entire screen with blank characters */ for(Index = 0; Index < VgaWidth * VgaHeight; Index++) { VgaBuffer[Index] = Blank; } /* Reset cursor position to the top-left corner */ CursorX = 0; CursorY = 0; /* Update the hardware cursor position */ UpdateCursor(); } /** * Formats the input string and prints it out to the screen. * * @param Format * The formatted string that is to be written to the output. * * @param ... * Depending on the format string, this routine might expect a sequence of additional arguments. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID BiosUtils::Print(IN PCWSTR Format, IN ...) { RTL_PRINT_CONTEXT PrintContext; VA_LIST Arguments; /* Initialise the print contexts */ PrintContext.WriteWideCharacter = PutChar; /* Initialise the va_list */ VA_START(Arguments, Format); /* Format and print the string to the stdout */ RTL::WideString::FormatWideString(&PrintContext, (PWCHAR)Format, Arguments); /* Clean up the va_list */ VA_END(Arguments); } /** * Writes a single wide character to the screen using legacy BIOS VGA text mode. * * @param Character * The wide character to be printed. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL XTSTATUS BiosUtils::PutChar(IN WCHAR Character) { VOLATILE PUSHORT VgaBuffer = (PUSHORT)0xB8000; USHORT VgaCharacter; /* Handle special characters */ if(Character == L'\n') { /* Move to the next line */ CursorX = 0; CursorY++; } else if(Character == L'\r') { /* Move to the beginning of the current line */ CursorX = 0; } else { /* Print character and move cursor to the right */ VgaCharacter = (0x0F << 8) | (Character & 0xFF); VgaBuffer[CursorY * VgaWidth + CursorX] = VgaCharacter; CursorX++; } /* Handle moving to the next line if cursor is at the end of the line */ if(CursorX >= VgaWidth) { CursorX = 0; CursorY++; } /* Handle scrolling if cursor is at the end of the screen */ if(CursorY >= VgaHeight) { ScrollScreen(); CursorY = VgaHeight - 1; } /* Update the hardware cursor position */ UpdateCursor(); /* Return success */ return STATUS_EFI_SUCCESS; } /** * Scrolls the entire screen content up by one line and clears the last line. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID BiosUtils::ScrollScreen() { VOLATILE PUSHORT VgaBuffer = (PUSHORT)0xB8000; USHORT Blank; UINT Index; /* Set blank character */ Blank = (0x0F << 8) | L' '; /* Move every line up by one */ for(Index = 0; Index < (VgaHeight - 1) * VgaWidth; Index++) { VgaBuffer[Index] = VgaBuffer[Index + VgaWidth]; } /* Clear the last line */ for(Index = (VgaHeight - 1) * VgaWidth; Index < VgaHeight * VgaWidth; Index++) { VgaBuffer[Index] = Blank; } } /** * Updates the hardware cursor position on the screen. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID BiosUtils::UpdateCursor() { USHORT Position; /* Calculate cursor position */ Position = CursorY * VgaWidth + CursorX; /* Send command to set the high byte of the cursor position */ HL::IoPort::WritePort8(0x3D4, 0x0E); HL::IoPort::WritePort8(0x3D5, (UCHAR)((Position >> 8) & 0xFF)); /* Send command to set the low byte of the cursor position */ HL::IoPort::WritePort8(0x3D4, 0x0F); HL::IoPort::WritePort8(0x3D5, (UCHAR)(Position & 0xFF)); } ================================================ FILE: boot/xtldr/bootutil.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/bootutil.cc * DESCRIPTION: Helper functions used by the boot protocol during system startup * DEVELOPERS: Aiken Harris */ #include /** * Checks if a specific option exists in the list of provided boot parameters. * * @param Parameters * A pointer to the wide-character string containing the boot parameters, separated by spaces. * * @param Needle * A pointer to the wide-character string representing the kernel option to find. * * @return This routine returns TRUE if the option is found, otherwise FALSE. * * @since XT 1.0 */ XTCDECL BOOLEAN BootUtils::GetBooleanParameter(IN PCWSTR Parameters, IN PCWSTR Needle) { PCWSTR CurrentPosition, TokenEnd, TokenStart; SIZE_T NeedleLength, TokenLength; /* Validate input data and ensure the option is not an empty string */ if(Parameters == NULLPTR || Needle == NULLPTR || *Needle == L'\0') { /* One of the parameters was invalid */ return FALSE; } CurrentPosition = Parameters; NeedleLength = RTL::WideString::WideStringLength(Needle, 0); /* Iterate through the entire parameters string */ while(*CurrentPosition != L'\0') { /* Skip any leading whitespace to find the start of the token */ while(*CurrentPosition == L' ') { CurrentPosition++; } /* Check if end of the string has been reached */ if(*CurrentPosition == L'\0') { /* End of string reached, no more tokens */ break; } /* Identify the boundaries of the current token */ TokenStart = CurrentPosition; TokenEnd = TokenStart; while(*TokenEnd != L'\0' && *TokenEnd != L' ') { TokenEnd++; } /* Calculate the length of the token found */ TokenLength = TokenEnd - TokenStart; /* Compare the token length */ if(TokenLength == NeedleLength) { /* Length matches, compare the strings */ if(RTL::WideString::CompareWideStringInsensitive(TokenStart, Needle, NeedleLength) == 0) { /* A match was found */ return TRUE; } } /* Move the position past the current token to continue the search */ CurrentPosition = TokenEnd; } /* No match was found */ return FALSE; } ================================================ FILE: boot/xtldr/config.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/config.cc * DESCRIPTION: XT Boot Loader Configuration * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Returns a boolean value of the specified configuration key. * * @param ConfigName * Specifies the configuration key to return its boolean representation. * * @return This routine returns a boolean representation of the configuration value. * * @since XT 1.0 */ XTCDECL BOOLEAN Configuration::GetBooleanValue(IN PCWSTR ConfigName) { PWCHAR Value; /* Get config value */ GetValue(ConfigName, &Value); /* Check if option is enabled */ if(RTL::WideString::CompareWideStringInsensitive(Value, L"ENABLED", 0) == 0 || RTL::WideString::CompareWideStringInsensitive(Value, L"ON", 0) == 0 || RTL::WideString::CompareWideStringInsensitive(Value, L"TRUE", 0) == 0 || RTL::WideString::CompareWideStringInsensitive(Value, L"YES", 0) == 0) { /* This option is enabled */ return TRUE; } /* Return FALSE by default */ return FALSE; } /** * @brief Retrieves the value of a specific OS boot option from a list. * * @param Options * A pointer to the head of a list of XTBL_CONFIG_ENTRY structures. * * @param OptionName * A pointer to wide string that contains the name of the boot option to retrieve. * * @param OptionValue * A pointer to a variable that receives a pointer to the retrieved boot option's value. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Configuration::GetBootOptionValue(IN PLIST_ENTRY Options, IN PCWSTR OptionName, OUT PWCHAR *OptionValue) { PXTBL_CONFIG_ENTRY ConfigEntry; PLIST_ENTRY ConfigList; ULONG KeyLength, ValueLength; EFI_STATUS Status; /* Assume the option will not be found */ *OptionValue = NULLPTR; /* Get the length of the option name we are looking for */ KeyLength = RTL::WideString::WideStringLength(OptionName, 0); /* Start iterating from the first entry in the options list */ ConfigList = Options->Flink; while(ConfigList != Options) { /* Get the container record for the current config entry */ ConfigEntry = CONTAIN_RECORD(ConfigList, XTBL_CONFIG_ENTRY, Flink); /* Compare the current entry's name with the requested option name */ if(RTL::WideString::CompareWideStringInsensitive(ConfigEntry->Name, OptionName, KeyLength) == 0) { /* Found the option, now prepare to copy its value */ ValueLength = RTL::WideString::WideStringLength(ConfigEntry->Value, 0); /* Allocate memory for the output value string */ Status = Memory::AllocatePool((ValueLength + 1) * sizeof(WCHAR), (PVOID *)OptionValue); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, print debug message and return status code */ Debug::Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status); *OptionValue = NULLPTR; return Status; } /* Copy the value and NULL-terminate the new string */ RTL::Memory::CopyMemory(*OptionValue, ConfigEntry->Value, ValueLength * sizeof(WCHAR)); (*OptionValue)[ValueLength] = L'\0'; /* Successfully retrieved the option value, return success */ return STATUS_EFI_SUCCESS; } /* Move to the next entry in the list */ ConfigList = ConfigList->Flink; } /* Option not found */ return STATUS_EFI_NOT_FOUND; } /** * Retrieves the list of user-editable boot options. * * @param OptionsArray * A pointer to a variable that will receive the pointer to the array of editable option names. * * @param OptionsCount * A pointer to a variable that will be updated with the number of elements in the OptionsArray. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Configuration::GetEditableOptions(OUT PCWSTR **OptionsArray, OUT PULONG OptionsCount) { ULONG Count = 0; /* Return a pointer to the global array of editable options */ *OptionsArray = EditableConfigOptions; /* Calculate the number of elements in the array */ while(EditableConfigOptions[Count]) { Count++; } /* Return the number of elements */ *OptionsCount = Count; } /** * Returns a value of the specified configuration key. * * @param ConfigName * Specifies the configuration key to return its value. * * @return This routine returns a pointer to the configuration value, or NULLPTR if key was not found. * * @since XT 1.0 */ XTCDECL EFI_STATUS Configuration::GetValue(IN PCWSTR ConfigName, OUT PWCHAR *ConfigValue) { PXTBL_CONFIG_ENTRY ConfigEntry; PLIST_ENTRY ConfigListEntry; SIZE_T KeyLength, ValueLength; EFI_STATUS Status; PWCHAR Value; /* Assume the option will not be found */ *ConfigValue = NULLPTR; /* Get config entry name length */ KeyLength = RTL::WideString::WideStringLength(ConfigName, 0); /* Iterate through config entries */ ConfigListEntry = Config.Flink; while(ConfigListEntry != &Config) { /* Get config entry */ ConfigEntry = CONTAIN_RECORD(ConfigListEntry, XTBL_CONFIG_ENTRY, Flink); /* Check if requested configuration found */ if(RTL::WideString::CompareWideStringInsensitive(ConfigEntry->Name, ConfigName, KeyLength) == 0) { /* Get value length */ ValueLength = RTL::WideString::WideStringLength(ConfigEntry->Value, 0); /* Allocate memory for value */ Status = Memory::AllocatePool((ValueLength + 1) * sizeof(WCHAR), (PVOID *)&Value); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, return NULLPTR */ Debug::Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status); return Status; } /* Copy value and return it */ RTL::Memory::CopyMemory(Value, ConfigEntry->Value, ValueLength * sizeof(WCHAR)); Value[ValueLength] = L'\0'; *ConfigValue = Value; return STATUS_EFI_SUCCESS; } /* Move to the next config entry */ ConfigListEntry = ConfigListEntry->Flink; } /* Config entry not found, return NULLPTR */ return STATUS_EFI_NOT_FOUND; } /** * Initializes a list of operating systems for XTLDR boot menu. * * @param MenuEntries * Supplies a pointer to memory area where operating systems list will be stored. * * @param EntriesCount * Supplies a pointer to memory area where number of menu entries will be stored. * * @param DefaultId * Supplies a pointer to memory area where ID of default menu entry will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL EFI_STATUS Configuration::InitializeBootMenuList(IN ULONG MaxNameLength, OUT PXTBL_BOOTMENU_ITEM *MenuEntries, OUT PULONG EntriesCount, OUT PULONG DefaultId) { EFI_GUID VendorGuid = XT_BOOT_LOADER_PROTOCOL_GUID; PWCHAR DefaultMenuEntry, LastBooted, MenuEntryName, VisibleName; PLIST_ENTRY MenuEntrySectionList, MenuEntryList; PXTBL_CONFIG_SECTION MenuEntrySection; PXTBL_CONFIG_ENTRY MenuEntryOption; ULONG DefaultOS, NameLength,NumberOfEntries; PXTBL_BOOTMENU_ITEM OsList; EFI_STATUS Status; /* Set default values */ DefaultOS = 0; NumberOfEntries = 0; /* Get default menu entry from configuration */ Configuration::GetValue(L"DEFAULT", &DefaultMenuEntry); /* Check if configuration allows to use last booted OS */ if(Configuration::GetBooleanValue(L"KEEPLASTBOOT")) { /* Attempt to get last booted Operating System from NVRAM */ Status = EfiUtils::GetEfiVariable(&VendorGuid, L"XtLdrLastBootOS", (PVOID*)&LastBooted); if(Status == STATUS_EFI_SUCCESS) { /* Set default menu entry to last booted OS */ DefaultMenuEntry = LastBooted; } } /* Iterate through menu items to get a total number of entries */ MenuEntrySectionList = BootMenuList->Flink; while(MenuEntrySectionList != BootMenuList) { /* Increase number of menu entries, and simply get next item */ NumberOfEntries++; MenuEntrySectionList = MenuEntrySectionList->Flink; } /* Allocate memory for the OS list depending on the item count */ Status = Memory::AllocatePool(NumberOfEntries * sizeof(XTBL_BOOTMENU_ITEM), (PVOID*)&OsList); if(Status != STATUS_EFI_SUCCESS || !OsList) { /* Memory allocation failure */ return STATUS_EFI_OUT_OF_RESOURCES; } /* Reset counter and iterate through all menu items once again */ NumberOfEntries = 0; MenuEntrySectionList = BootMenuList->Flink; while(MenuEntrySectionList != BootMenuList) { /* NULLify menu entry name */ MenuEntryName = NULLPTR; /* Get menu section */ MenuEntrySection = CONTAIN_RECORD(MenuEntrySectionList, XTBL_CONFIG_SECTION, Flink); /* Check if this is the default menu entry */ if((RTL::WideString::WideStringLength(MenuEntrySection->SectionName, 0) == RTL::WideString::WideStringLength(DefaultMenuEntry, 0)) && (RTL::WideString::CompareWideStringInsensitive(MenuEntrySection->SectionName, DefaultMenuEntry, 0) == 0)) { /* Set default OS ID */ DefaultOS = NumberOfEntries; } /* Iterate through all entry parameters */ MenuEntryList = MenuEntrySection->Options.Flink; while(MenuEntryList != &MenuEntrySection->Options) { /* Get menu entry parameter */ MenuEntryOption = CONTAIN_RECORD(MenuEntryList, XTBL_CONFIG_ENTRY, Flink); /* Check if this is the menu entry display name */ if(RTL::WideString::CompareWideStringInsensitive(MenuEntryOption->Name, L"SYSTEMNAME", 0) == 0) { /* Set menu entry display name */ MenuEntryName = MenuEntryOption->Value; } /* Get next parameter for this menu entry */ MenuEntryList = MenuEntryList->Flink; } /* Add OS to the boot menu list */ OsList[NumberOfEntries].FullName = MenuEntryName; OsList[NumberOfEntries].ShortName = MenuEntrySection->SectionName; OsList[NumberOfEntries].Options = &MenuEntrySection->Options; /* Check if the menu entry name fits the maximum length */ NameLength = RTL::WideString::WideStringLength(MenuEntryName, 0); if(NameLength > MaxNameLength) { /* Menu entry name is too long, allocate memory for shorter name visible in the boot menu */ Status = Memory::AllocatePool((MaxNameLength + 1) * sizeof(WCHAR), (PVOID*)&VisibleName); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return STATUS_EFI_OUT_OF_RESOURCES; } /* Copy shorter name and append "..." at the end */ RTL::Memory::CopyMemory(VisibleName, MenuEntryName, (MaxNameLength - 3) * sizeof(WCHAR)); RTL::Memory::CopyMemory(VisibleName + MaxNameLength - 3, L"...", 3 * sizeof(WCHAR)); VisibleName[MaxNameLength] = L'\0'; /* Set visible menu entry name */ OsList[NumberOfEntries].EntryName = VisibleName; } else { /* Menu entry name fits the maximum length, use it as is */ OsList[NumberOfEntries].EntryName = MenuEntryName; } /* Get next menu entry */ MenuEntrySectionList = MenuEntrySectionList->Flink; NumberOfEntries++; } /* Set return values */ *DefaultId = DefaultOS; *EntriesCount = NumberOfEntries; *MenuEntries = OsList; /* Return success */ return STATUS_EFI_SUCCESS; } /** * Initializes the XTLDR configuration subsystem. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Configuration::InitializeConfiguration() { /* Initialize XTLDR configuration linked lists */ RTL::LinkedList::InitializeListHead(&Config); } /** * Loads and parses XTLDR configuration file. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Configuration::LoadConfiguration() { PLIST_ENTRY SectionListEntry; EFI_STATUS Status; PCHAR ConfigData; /* Initialize configuration pointer */ RTL::LinkedList::InitializeListHead(&ConfigSections); /* Read data from configuration file */ Status = ReadConfigFile(XTBL_LOADER_DIRECTORY_PATH, L"XTLDR.INI", &ConfigData); if(Status != STATUS_EFI_SUCCESS) { /* Failed to read config file, try with architecture specific directory */ Status = ReadConfigFile(XTBL_ARCH_LOADER_DIRECTORY_PATH, L"XTLDR.INI", &ConfigData); } /* Check if configuration was read successfully */ if(Status != STATUS_EFI_SUCCESS) { /* Failed to load configuration */ Debug::Print(L"Failed to load FS0:/EFI/BOOT/XTLDR/XTLDR.INI configuration file (Status Code: 0x%zX)\n", Status); return Status; } /* Parse configuration data */ Status = ParseConfigFile(ConfigData, &ConfigSections); if(Status != STATUS_EFI_SUCCESS) { /* Failed to parse configuration */ Debug::Print(L"Failed to parse FS0:/EFI/BOOT/XTLDR/XTLDR.INI configuration file (Status Code: 0x%zX)\n", Status); return Status; } /* Iterate through config sections */ SectionListEntry = ConfigSections.Flink; while(SectionListEntry != &ConfigSections) { /* Get config section */ PXTBL_CONFIG_SECTION Section = CONTAIN_RECORD(SectionListEntry, XTBL_CONFIG_SECTION, Flink); /* Look for global XTLDR configuration section */ if(RTL::WideString::CompareWideStringInsensitive(Section->SectionName, L"XTLDR", 5) == 0) { /* Update global configuration */ UpdateConfiguration(&Section->Options); /* Remove XTLDR section from the list */ RTL::LinkedList::RemoveEntryList(SectionListEntry); break; } /* Move to the next section */ SectionListEntry = SectionListEntry->Flink; } /* Update boot menu OS list */ BootMenuList = &ConfigSections; /* Return success */ return STATUS_EFI_SUCCESS; } /** * Parses command line arguments and updates global configuration. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL EFI_STATUS Configuration::ParseCommandLine(VOID) { EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; PEFI_LOADED_IMAGE_PROTOCOL LoadedImage; PWCHAR Argument, Key, LastArg, Value; PXTBL_CONFIG_ENTRY Option; EFI_STATUS Status; SIZE_T KeyLength, ValueLength; LIST_ENTRY Config; /* Initialize configuration list */ RTL::LinkedList::InitializeListHead(&Config); /* Handle loaded image protocol */ Status = XtLoader::GetEfiSystemTable()->BootServices->HandleProtocol(XtLoader::GetEfiImageHandle(), &LIPGuid, (PVOID *)&LoadedImage); if(Status == STATUS_EFI_SUCCESS) { /* Check if launched from UEFI shell */ if(LoadedImage && LoadedImage->LoadOptions) { /* Tokenize provided options */ Argument = RTL::WideString::TokenizeWideString((PWCHAR)LoadedImage->LoadOptions, L" ", &LastArg); /* Iterate over all arguments passed to boot loader */ while(Argument != NULLPTR) { /* Store key name */ Key = Argument; /* Find end of the key */ while(*Argument != L'=' && *Argument != L'\0' && *Argument != L'\n') { /* Advance to the next character */ Argument++; } /* Mark end of the key and advance to the next character */ *Argument = L'\0'; Argument++; /* Store value */ Value = Argument; /* Find end of the value */ while(*Argument != L'\0' && *Argument != L'\n') { /* Advance to the next character */ Argument++; } /* Mark end of the value and advance to the next character */ *Argument = L'\0'; Argument++; /* Get length of the key and its value */ KeyLength = RTL::WideString::WideStringLength(Key, 0); ValueLength = RTL::WideString::WideStringLength(Value, 0); /* Check if argument is valid */ if(KeyLength == 0 || ValueLength == 0) { /* Invalid argument, skip to the next one */ continue; } /* Allocate memory for new option */ Status = Memory::AllocatePool(sizeof(XTBL_CONFIG_ENTRY), (PVOID*)&Option); if(Status == STATUS_EFI_SUCCESS) { /* Allocate more memory for option name */ Status = Memory::AllocatePool(sizeof(WCHAR) * (KeyLength + 1), (PVOID*)&Option->Name); if(Status == STATUS_EFI_SUCCESS) { /* Allocate even more memory for option value */ Status = Memory::AllocatePool(sizeof(WCHAR) * (ValueLength + 1), (PVOID*)&Option->Value); } } if(Status != STATUS_EFI_SUCCESS) { /* Some memory allocation failed */ return Status; } /* Set entry name and value */ RTL::Memory::CopyMemory(Option->Name, Key, (KeyLength * sizeof(WCHAR))); RTL::Memory::CopyMemory(Option->Value, Value, (ValueLength * sizeof(WCHAR))); Option->Name[KeyLength] = L'\0'; Option->Value[ValueLength] = L'\0'; /* Add entry to the list */ RTL::LinkedList::InsertTailList(&Config, &Option->Flink); /* Take next argument */ Argument = RTL::WideString::TokenizeWideString(NULLPTR, L" ", &LastArg); } /* Update global configuration */ UpdateConfiguration(&Config); } } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Parses configuration INI file. * * @param RawConfig * Suplies a pointer to configuration INI file to be parsed. * * @param Configuration * Supplies a pointer to memory region where parsed configuration will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Configuration::ParseConfigFile(IN CONST PCHAR RawConfig, OUT PLIST_ENTRY Configuration) { SIZE_T SectionLength, KeyLength, ValueLength; PCHAR InputData, Key, SectionName, Value; PXTBL_CONFIG_SECTION Section; PXTBL_CONFIG_ENTRY Option; EFI_STATUS Status; /* Initialize pointers */ InputData = RawConfig; Section = NULLPTR; Option = NULLPTR; SectionName = NULLPTR; Key = NULLPTR; Value = NULLPTR; /* Analyze configuration data until end of file is reached */ while(*InputData != '\0') { if(*InputData == ';' || *InputData == '#') { /* Skip comment until end of the line */ while(*InputData != '\0' && *InputData != '\n') { /* Advance to the next character */ InputData++; } } else if(*InputData == ' ' || *InputData == '\t' || *InputData == '\r' || *InputData == '\n') { /* Skip whitespaces */ InputData++; } else if(*InputData == '[') { /* Skip leading bracket */ InputData++; /* Store section name */ SectionName = InputData; /* Find end of the section name */ while(*InputData != ']' && *InputData != '\0' && *InputData != '\r' && *InputData != '\n') { /* Advance to the next character */ InputData++; } /* Check if end of the section name is reached */ if(*InputData != ']') { /* Section name does not end */ return STATUS_EFI_INVALID_PARAMETER; } /* Mark end of the section name and advance to the next character */ *InputData = '\0'; InputData++; /* Remove leading and trailing spaces from section name */ SectionName = RTL::String::TrimString(SectionName); /* Find length of the section name */ SectionLength = RTL::String::StringLength(SectionName, 0); /* Allocate memory for new section */ Status = Memory::AllocatePool(sizeof(XTBL_CONFIG_SECTION), (PVOID*)&Section); if(Status == STATUS_EFI_SUCCESS) { /* Allocate more memory for section name */ Status = Memory::AllocatePool(sizeof(WCHAR) * (SectionLength + 1), (PVOID*)&Section->SectionName); } if(Status != STATUS_EFI_SUCCESS) { /* Some memory allocation failed */ return Status; } /* Initialize new section and convert its name to wide string */ RTL::LinkedList::InitializeListHead(&Section->Options); RTL::String::StringToWideString(Section->SectionName, (PCSTR*)&SectionName, SectionLength); /* Ensure string is NULL-terminated and add new section to the configuration list */ Section->SectionName[SectionLength] = L'\0'; RTL::LinkedList::InsertTailList(Configuration, &Section->Flink); } else { /* Store key */ Key = InputData; /* Find end of the key */ while(*InputData != '=' && *InputData != '\0' && *InputData != '\r' && *InputData != '\n') { /* Advance to the next character */ InputData++; } /* Check if end of the key is reached */ if(*InputData != '=') { /* Key name does not end */ return STATUS_EFI_INVALID_PARAMETER; } /* Mark end of the key and advance to the next character */ *InputData = 0; InputData++; /* Skip all leading spaces in the value */ while(*InputData == ' ') { /* Advance to the next character */ InputData++; } /* Store value */ Value = InputData; /* Find end of the value */ while(*InputData != '\0' && *InputData != '\r' && *InputData != '\n') { /* Advance to the next character */ InputData++; } /* Mark end of the value and advance to the next character */ *InputData = 0; InputData++; /* Remove leading and trailing spaces from key and value */ Key = RTL::String::TrimString(Key); Value = RTL::String::TrimString(Value); /* Find length of the key and its value */ KeyLength = RTL::String::StringLength(Key, 0); ValueLength = RTL::String::StringLength(Value, 0); /* Allocate memory for new option */ Status = Memory::AllocatePool(sizeof(XTBL_CONFIG_ENTRY), (PVOID*)&Option); if(Status == STATUS_EFI_SUCCESS) { /* Allocate more memory for option name */ Status = Memory::AllocatePool(sizeof(WCHAR) * (KeyLength + 1), (PVOID*)&Option->Name); if(Status == STATUS_EFI_SUCCESS) { /* Allocate even more memory for option value */ Status = Memory::AllocatePool(sizeof(WCHAR) * (ValueLength + 1), (PVOID*)&Option->Value); } } if(Status != STATUS_EFI_SUCCESS) { /* Some memory allocation failed */ return Status; } /* Remove leading quotes from the value */ if(*Value == '"' || *Value == '\'') { Value++; } /* Remove trailing quotes from the value */ if(Value[ValueLength - 2] == '"' || Value[ValueLength - 2] == '\'') { Value[ValueLength - 2] = '\0'; } /* Convert key and value to wide strings */ RTL::String::StringToWideString(Option->Name, (PCSTR*)&Key, RTL::String::StringLength(Key, 0) + 1); RTL::String::StringToWideString(Option->Value, (PCSTR*)&Value, RTL::String::StringLength(Value, 0) + 1); /* Ensure strings are NULL-terminated and add new option to the list */ Option->Name[KeyLength] = L'\0'; Option->Value[ValueLength] = L'\0'; RTL::LinkedList::InsertTailList(&Section->Options, &Option->Flink); } } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Loads configuration file from the specified directory on the FS0:/ drive. * * @param ConfigDirectory * Specifies a path to the directory containing the configuration file. * * @param ConfigFile * Specifies the name of the configuration file. * * @param ConfigData * Provides a buffer to store the data read from the configuration file. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Configuration::ReadConfigFile(IN PCWSTR ConfigDirectory, IN PCWSTR ConfigFile, OUT PCHAR *ConfigData) { PEFI_FILE_HANDLE DirHandle, FsHandle; EFI_HANDLE DiskHandle; EFI_STATUS Status; SIZE_T FileSize; /* Open EFI volume */ Status = Volume::OpenVolume(NULLPTR, &DiskHandle, &FsHandle); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open a volume */ return Status; } /* Open specified directory, containing the configuration file and close the FS immediately */ Status = FsHandle->Open(FsHandle, &DirHandle, (PWCHAR)ConfigDirectory, EFI_FILE_MODE_READ, 0); FsHandle->Close(FsHandle); /* Check if directory opened successfully */ if(Status != STATUS_EFI_SUCCESS) { /* Failed to open directory */ Volume::CloseVolume(&DiskHandle); return Status; } /* Read configuration file and close directory */ Status = Volume::ReadFile(DirHandle, ConfigFile, (PVOID *)ConfigData, &FileSize); DirHandle->Close(DirHandle); /* Close EFI volume */ Volume::CloseVolume(&DiskHandle); /* Return read status */ return Status; } /** * Sets the value of a specific OS boot option in a list, or adds it if it doesn't exist. * * @param Options * A pointer to the head of a list of XTBL_CONFIG_ENTRY structures. * * @param OptionName * A pointer to a wide string that contains the name of the boot option to set. * * @param OptionValue * A pointer to a wide string that contains the new value for the boot option. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Configuration::SetBootOptionValue(IN PLIST_ENTRY Options, IN PCWSTR OptionName, IN PCWSTR OptionValue) { PXTBL_CONFIG_ENTRY ConfigEntry; PLIST_ENTRY ConfigList; ULONG Length; EFI_STATUS Status; /* Get the length of the option name we are looking for */ Length = RTL::WideString::WideStringLength(OptionName, 0); /* Start iterating from the first entry in the options list */ ConfigList = Options->Flink; while(ConfigList != Options) { /* Get the container record for the current config entry */ ConfigEntry = CONTAIN_RECORD(ConfigList, XTBL_CONFIG_ENTRY, Flink); /* Compare the current entry's name with the requested option name */ if(RTL::WideString::CompareWideStringInsensitive(ConfigEntry->Name, OptionName, Length) == 0) { /* Found the option, get its length */ Length = RTL::WideString::WideStringLength(OptionValue, 0); /* Reallocate memory for the new value */ Status = Memory::FreePool(ConfigEntry->Value); if(Status != STATUS_EFI_SUCCESS) { /* Failed to free memory, return status code */ return Status; } /* Allocate new memory for the updated value */ Status = Memory::AllocatePool((Length + 1) * sizeof(WCHAR), (PVOID *)&ConfigEntry->Value); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, print debug message and return status code */ Debug::Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\\n", Status); return Status; } /* Copy the value and NULL-terminate the new string */ RTL::Memory::CopyMemory(ConfigEntry->Value, OptionValue, Length * sizeof(WCHAR)); ConfigEntry->Value[Length] = L'\0'; return STATUS_EFI_SUCCESS; } /* Move to the next entry in the list */ ConfigList = ConfigList->Flink; } /* Option not found, allocate memory for the new one */ Status = Memory::AllocatePool(sizeof(XTBL_CONFIG_ENTRY), (PVOID *)&ConfigEntry); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, print debug message and return status code */ Debug::Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\\n", Status); return Status; } /* Allocate memory for the option name */ Length = RTL::WideString::WideStringLength(OptionName, 0); Status = Memory::AllocatePool((Length + 1) * sizeof(WCHAR), (PVOID *)&ConfigEntry->Name); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, print debug message and return status code */ Debug::Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\\n", Status); Memory::FreePool(ConfigEntry); return Status; } /* Copy the option name and NULL-terminate the new string */ RTL::Memory::CopyMemory(ConfigEntry->Name, OptionName, Length * sizeof(WCHAR)); ConfigEntry->Name[Length] = L'\0'; /* Allocate memory for the option value */ Length = RTL::WideString::WideStringLength(OptionValue, 0); Status = Memory::AllocatePool((Length + 1) * sizeof(WCHAR), (PVOID *)&ConfigEntry->Value); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, print debug message and return status code */ Debug::Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\\n", Status); Memory::FreePool(ConfigEntry->Name); Memory::FreePool(ConfigEntry); return Status; } /* Copy the value and NULL-terminate the new string */ RTL::Memory::CopyMemory(ConfigEntry->Value, OptionValue, Length * sizeof(WCHAR)); ConfigEntry->Value[Length] = L'\0'; /* Insert the new config entry at the end of the options list */ RTL::LinkedList::InsertTailList(Options, &ConfigEntry->Flink); /* Return success */ return STATUS_EFI_SUCCESS; } /** * Updates existing configuration value. * * @param ConfigName * Specifies the configuration key to update. * * @param ConfigValue * Specifies the new configuration value. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Configuration::SetValue(IN PCWSTR ConfigName, IN PCWSTR ConfigValue) { PXTBL_CONFIG_ENTRY ConfigEntry; PLIST_ENTRY ConfigListEntry; EFI_STATUS Status; SIZE_T Length; /* Get config entry name length */ Length = RTL::WideString::WideStringLength(ConfigName, 0); /* Iterate through config entries */ ConfigListEntry = Config.Flink; while(ConfigListEntry != &Config) { /* Get config entry */ ConfigEntry = CONTAIN_RECORD(ConfigListEntry, XTBL_CONFIG_ENTRY, Flink); /* Check if requested configuration found */ if(RTL::WideString::CompareWideStringInsensitive(ConfigEntry->Name, ConfigName, Length) == 0) { /* Check new config value length */ Length = RTL::WideString::WideStringLength(ConfigValue, 0); /* Reallocate memory for new config value */ Status = Memory::FreePool(ConfigEntry->Value); if(Status == STATUS_EFI_SUCCESS) { /* Successfully freed memory, allocate a new pool */ Status = Memory::AllocatePool((Length + 1) * sizeof(WCHAR), (PVOID *)&ConfigEntry->Value); } /* Check memory reallocation status */ if(Status != STATUS_EFI_SUCCESS) { /* Failed to reallocate memory */ return Status; } /* Update config value */ RTL::Memory::CopyMemory(ConfigEntry->Value, ConfigValue, Length * sizeof(WCHAR)); ConfigEntry->Value[Length] = L'\0'; /* Return success */ return STATUS_EFI_SUCCESS; } /* Move to the next config entry */ ConfigListEntry = ConfigListEntry->Flink; } /* Config entry not found */ return STATUS_EFI_NOT_FOUND; } /** * Adds new XTLDR configuration entries to the global configuration list. Existing entries are not overwritten. * * @param NewConfig * Supplies a pointer to a linked list containing new configuration entries. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Configuration::UpdateConfiguration(IN PLIST_ENTRY NewConfig) { PXTBL_CONFIG_ENTRY ConfigEntry; PWCHAR ConfigValue; PLIST_ENTRY ConfigListEntry, NextListEntry; /* Iterate through new config entries */ ConfigListEntry = NewConfig->Flink; while(ConfigListEntry != NewConfig) { /* Get new config entry */ ConfigEntry = CONTAIN_RECORD(ConfigListEntry, XTBL_CONFIG_ENTRY, Flink); /* Get next config entry */ NextListEntry = ConfigListEntry->Flink; /* Make sure config entry does not exist yet */ GetValue(ConfigEntry->Name, &ConfigValue); if(ConfigValue == NULLPTR) { /* Remove new config entry from input list and put it into global config list */ RTL::LinkedList::RemoveEntryList(&ConfigEntry->Flink); RTL::LinkedList::InsertTailList(&Config, &ConfigEntry->Flink); } /* Move to the next new config entry */ ConfigListEntry = NextListEntry; } } ================================================ FILE: boot/xtldr/console.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/console.cc * DESCRIPTION: EFI console support * DEVELOPERS: Rafal Kupiec */ #include /** * Clears a specified line on the UEFI text console. * * @param LineNo * Supplies a line number to clear. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Console::ClearLine(IN ULONGLONG LineNo) { UINT_PTR Index, ResX, ResY; /* Query console mode */ QueryMode(&ResX, &ResY); /* Set cursor position and clear line */ SetCursorPosition(0, LineNo); for(Index = 0; Index < ResX; Index++) { /* Clear line */ Write(L" "); } } /** * This routine clears the UEFI console screen. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Console::ClearScreen() { /* Clear screen */ XtLoader::GetEfiSystemTable()->ConOut->ClearScreen(XtLoader::GetEfiSystemTable()->ConOut); } /** * Disables the cursor on the UEFI console. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Console::DisableCursor() { XtLoader::GetEfiSystemTable()->ConOut->EnableCursor(XtLoader::GetEfiSystemTable()->ConOut, FALSE); } /** * Enables the cursor on the UEFI console. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Console::EnableCursor() { XtLoader::GetEfiSystemTable()->ConOut->EnableCursor(XtLoader::GetEfiSystemTable()->ConOut, TRUE); } /** * This routine initializes the EFI console. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL VOID Console::InitializeConsole() { /* Clear console buffers */ XtLoader::GetEfiSystemTable()->ConIn->Reset(XtLoader::GetEfiSystemTable()->ConIn, TRUE); XtLoader::GetEfiSystemTable()->ConOut->Reset(XtLoader::GetEfiSystemTable()->ConOut, TRUE); XtLoader::GetEfiSystemTable()->StdErr->Reset(XtLoader::GetEfiSystemTable()->StdErr, TRUE); /* Make sure that current console mode is 80x25 characters, as some broken EFI implementations might * set different mode that do not fit on the screen, causing a text to be displayed offscreen */ if(XtLoader::GetEfiSystemTable()->ConOut->Mode->Mode != 0) { /* Set console mode to 0, which is standard, 80x25 text mode */ SetMode(0); } /* Clear screen and enable cursor */ SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); ClearScreen(); EnableCursor(); } /** * This routine formats the input string and prints it out to the stdout and serial console. * * @param Format * The formatted string that is to be written to the output. * * @param ... * Depending on the format string, this routine might expect a sequence of additional arguments. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Console::Print(IN PCWSTR Format, IN ...) { RTL_PRINT_CONTEXT ConsolePrintContext, SerialPrintContext; VA_LIST Arguments; /* Initialise the print contexts */ ConsolePrintContext.WriteWideCharacter = PutChar; SerialPrintContext.WriteWideCharacter = Debug::PutChar; /* Initialise the va_list */ VA_START(Arguments, Format); /* Format and print the string to the stdout */ RTL::WideString::FormatWideString(&ConsolePrintContext, (PWCHAR)Format, Arguments); /* Print to serial console only if not running under OVMF */ if(RTL::WideString::CompareWideString(XtLoader::GetEfiSystemTable()->FirmwareVendor, L"EDK II", 6) != 0) { /* Check if debugging enabled and if EFI serial port is fully initialized */ if(DEBUG && Debug::SerialPortReady()) { /* Format and print the string to the serial console */ RTL::WideString::FormatWideString(&SerialPrintContext, (PWCHAR)Format, Arguments); } } /* Clean up the va_list */ VA_END(Arguments); } /** * Writes a character to the default EFI console. * * @param Character * The integer promotion of the character to be written. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL XTSTATUS Console::PutChar(IN WCHAR Character) { WCHAR Buffer[2]; /* Check if character is a newline ('\n') */ if(Character == L'\n') { /* Print carriage return ('\r') as well */ PutChar(L'\r'); } /* Write character to the screen console */ Buffer[0] = Character; Buffer[1] = 0; XtLoader::GetEfiSystemTable()->ConOut->OutputString(XtLoader::GetEfiSystemTable()->ConOut, Buffer); /* Return success */ return STATUS_SUCCESS; } /** * Queries information concerning the output device’s supported text mode. * * @param ResX * Supplies a buffer to receive the horizontal resolution. * * @param ResY * Supplies a buffer to receive the vertical resolution. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Console::QueryMode(OUT PUINT_PTR ResX, OUT PUINT_PTR ResY) { XtLoader::GetEfiSystemTable()->ConOut->QueryMode(XtLoader::GetEfiSystemTable()->ConOut, XtLoader::GetEfiSystemTable()->ConOut->Mode->Mode, ResX, ResY); } /** * Reads a keystroke from the input device. * * @param Key * Supplies a pointer to the EFI_INPUT_KEY structure that will receive the keystroke. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL EFI_STATUS Console::ReadKeyStroke(OUT PEFI_INPUT_KEY Key) { /* Clear the key structure to prevent ghost keystrokes */ Key->ScanCode = 0; Key->UnicodeChar = 0; /* Read the keystroke from the EFI input console */ return XtLoader::GetEfiSystemTable()->ConIn->ReadKeyStroke(XtLoader::GetEfiSystemTable()->ConIn, Key); } /** * Resets the console input device and clears its input buffer. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Console::ResetInputBuffer() { XtLoader::GetEfiSystemTable()->ConIn->Reset(XtLoader::GetEfiSystemTable()->ConIn, FALSE); } /** * Sets the foreground and background colors. * * @param Attribute * Specifies the foreground and background colors (bits 0..3 are fg, and bits 4..6 are bg color). * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Console::SetAttributes(IN ULONGLONG Attributes) { XtLoader::GetEfiSystemTable()->ConOut->SetAttribute(XtLoader::GetEfiSystemTable()->ConOut, Attributes); } /** * Sets new coordinates of the console cursor position. * * @param PosX * Specifies the new X coordinate of the cursor. * * @param PosY * Specifies the new Y coordinate of the cursor. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Console::SetCursorPosition(IN ULONGLONG PosX, IN ULONGLONG PosY) { XtLoader::GetEfiSystemTable()->ConOut->SetCursorPosition(XtLoader::GetEfiSystemTable()->ConOut, PosX, PosY); } /** * Sets the output console device to the requested mode. * * @param Mode * Supplies a text mode number to set. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Console::SetMode(IN ULONGLONG Mode) { return XtLoader::GetEfiSystemTable()->ConOut->SetMode(XtLoader::GetEfiSystemTable()->ConOut, Mode); } /** * Displays the string on the device at the current cursor location. * * @param String * The string to be displayed. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Console::Write(IN PCWSTR String) { XtLoader::GetEfiSystemTable()->ConOut->OutputString(XtLoader::GetEfiSystemTable()->ConOut, (PWSTR)String); } ================================================ FILE: boot/xtldr/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/data.cc * DESCRIPTION: XT Boot Loader global and static data * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /* Legacy BIOS cursor X position */ USHORT BiosUtils::CursorX = 0; /* Legacy BIOS cursor Y position */ USHORT BiosUtils::CursorY = 0; /* Legacy BIOS screen height */ CONST USHORT BiosUtils::VgaHeight = 25; /* Legacy BIOS screen width */ CONST USHORT BiosUtils::VgaWidth = 80; /* XT Boot Loader menu list */ PLIST_ENTRY Configuration::BootMenuList = NULLPTR; /* XT Boot Loader configuration list */ LIST_ENTRY Configuration::Config; /* XT Boot Loader loaded configuration */ LIST_ENTRY Configuration::ConfigSections; /* List of user-editable boot options */ PCWSTR Configuration::EditableConfigOptions[] = { L"BootModules", L"SystemType", L"SystemPath", L"KernelFile", L"InitrdFile", L"HalFile", L"Parameters", NULLPTR }; /* XT Boot Loader serial ports list */ ULONG Debug::ComPortList[COMPORT_COUNT] = COMPORT_ADDRESS; /* A list of enabled debug ports */ ULONG Debug::EnabledDebugPorts; /* XT Boot Loader serial port handle */ CPPORT Debug::SerialPort; /* XT Boot Loader registered boot protocol list */ LIST_ENTRY Protocol::BootProtocols; /* XT Boot Loader protocol */ XTBL_LOADER_PROTOCOL Protocol::LoaderProtocol; /* XT Boot Loader loaded modules list */ LIST_ENTRY Protocol::LoadedModules; /* XT Boot Loader shell exit flag */ BOOLEAN Shell::ExitRequest; /* XT Boot Loader shell history buffer */ WCHAR Shell::History[XTBL_SH_HISTORY_ENTRIES][XTBL_SH_MAX_LINE_LENGTH]; /* XT Boot Loader shell history count */ ULONG Shell::HistoryCount = 0; /* XT Boot Loader shell history index */ ULONG Shell::HistoryIndex = 0; /* XT Boot Loader shell commands list */ LIST_ENTRY Shell::ShellCommands; /* List of available block devices */ LIST_ENTRY Volume::EfiBlockDevices; /* Pointer to the boot menu callback routine */ PBL_XT_BOOT_MENU XtLoader::BootMenu = NULLPTR; /* EFI Image Handle */ EFI_HANDLE XtLoader::EfiImageHandle; /* EFI System Table */ PEFI_SYSTEM_TABLE XtLoader::EfiSystemTable; /* XT Boot Loader status data */ XTBL_STATUS XtLoader::LoaderStatus = {0}; ================================================ FILE: boot/xtldr/debug.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/debug.cc * DESCRIPTION: XT Boot Loader debugging support * DEVELOPERS: Rafal Kupiec */ #include /** * Enables I/O space access to all serial controllers found on the PCI(E) root bridge. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Debug::ActivateSerialIOController() { EFI_GUID PciGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL PciDev; USHORT Bus, Device, Function, Command; UINT_PTR Index, PciHandleSize; PEFI_HANDLE PciHandle = NULLPTR; PCI_COMMON_HEADER PciHeader; EFI_STATUS Status; ULONGLONG Address; /* Allocate memory for single EFI_HANDLE, what should be enough in most cases */ PciHandleSize = sizeof(EFI_HANDLE); Status = Memory::AllocatePool(PciHandleSize, (PVOID*)&PciHandle); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Get all instances of PciRootBridgeIo */ Status = XtLoader::GetEfiSystemTable()->BootServices->LocateHandle(ByProtocol, &PciGuid, NULLPTR, &PciHandleSize, PciHandle); if(Status == STATUS_EFI_BUFFER_TOO_SMALL) { /* Reallocate more memory as requested by UEFI */ Memory::FreePool(PciHandle); Status = Memory::AllocatePool(PciHandleSize, (PVOID*)&PciHandle); if(Status != STATUS_EFI_SUCCESS) { /* Memory reallocation failure */ return Status; } /* Second attempt to get instances of PciRootBridgeIo */ Status = XtLoader::GetEfiSystemTable()->BootServices->LocateHandle(ByProtocol, &PciGuid, NULLPTR, &PciHandleSize, PciHandle); } /* Make sure successfully obtained PciRootBridgeIo instances */ if(Status != STATUS_EFI_SUCCESS) { /* Failed to get PciRootBridgeIo instances */ return Status; } /* Enumerate all devices for each handle, which decides a segment and a bus number range */ for(Index = 0; Index < (PciHandleSize / sizeof(EFI_HANDLE)); Index++) { /* Get inferface from the protocol */ Status = XtLoader::GetEfiSystemTable()->BootServices->HandleProtocol(PciHandle[Index], &PciGuid, (PVOID*)&PciDev); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get interface */ return Status; } /* Enumerate whole PCI bridge */ for(Bus = 0; Bus <= PCI_MAX_BRIDGE_NUMBER; Bus++) { /* Enumerate all devices for each bus */ for(Device = 0; Device < PCI_MAX_DEVICES; Device++) { /* Enumerate all functions for each devices */ for(Function = 0; Function < PCI_MAX_FUNCTION; Function++) { /* Read configuration space */ Address = ((ULONGLONG)((((UINT_PTR) Bus) << 24) + (((UINT_PTR) Device) << 16) + (((UINT_PTR) Function) << 8) + ((UINT_PTR) 0))); PciDev->Pci.Read(PciDev, EfiPciIoWidthUint32, Address, sizeof (PciHeader) / sizeof (UINT), &PciHeader); /* Check if device exists */ if(PciHeader.VendorId == PCI_INVALID_VENDORID) { /* Skip non-existen device */ continue; } /* Check if device is serial controller or multiport serial controller */ if(PciHeader.BaseClass == 0x07 && (PciHeader.SubClass == 0x00 || PciHeader.SubClass == 0x02)) { /* Enable I/O space access */ Address |= 0x4; Command = PCI_ENABLE_IO_SPACE; Status = PciDev->Pci.Write(PciDev, EfiPciIoWidthUint16, Address, 1, &Command); } } } } } /* Return SUCCESS */ return STATUS_EFI_SUCCESS; } /** * This routine initializes the XTLDR debug console. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Debug::InitializeDebugConsole() { ULONG PortAddress, PortNumber, BaudRate; PWCHAR DebugConfiguration, DebugPort, LastPort; EFI_STATUS Status; /* Set default serial port options */ PortAddress = 0; PortNumber = 0; BaudRate = 0; /* Get debug configuration */ Configuration::GetValue(L"DEBUG", &DebugConfiguration); /* Make sure any debug options are provided and debug console is not initialized yet */ if(DebugConfiguration && EnabledDebugPorts == 0) { /* Find all debug ports */ DebugPort = RTL::WideString::TokenizeWideString(DebugConfiguration, L";", &LastPort); /* Iterate over all debug ports */ while(DebugPort != NULLPTR) { /* Check what port is set for debugging */ if(RTL::WideString::CompareWideStringInsensitive(DebugPort, L"COM", 3) == 0) { /* Read COM port number */ DebugPort += 3; while(*DebugPort >= '0' && *DebugPort <= '9') { /* Get port number */ PortNumber *= 10; PortNumber += *DebugPort - '0'; DebugPort++; } /* Check if custom COM port address supplied */ if(PortNumber == 0 && RTL::WideString::CompareWideStringInsensitive(DebugPort, L":0x", 3) == 0) { /* COM port address provided */ DebugPort += 3; while((*DebugPort >= '0' && *DebugPort <= '9') || (*DebugPort >= 'A' && *DebugPort <= 'F') || (*DebugPort >= 'a' && *DebugPort <= 'f')) { /* Get port address */ PortAddress *= 16; if(*DebugPort >= '0' && *DebugPort <= '9') { PortAddress += *DebugPort - '0'; } else if(*DebugPort >= 'A' && *DebugPort <= 'F') { PortAddress += *DebugPort - 'A' + 10; } else if(*DebugPort >= 'a' && *DebugPort <= 'f') { PortAddress += *DebugPort - 'a' + 10; } DebugPort++; } } /* Look for additional COM port parameters */ if(*DebugPort == ',') { /* Baud rate provided */ DebugPort++; while(*DebugPort >= '0' && *DebugPort <= '9') { /* Get baud rate */ BaudRate *= 10; BaudRate += *DebugPort - '0'; DebugPort++; } } /* Enable debug port */ EnabledDebugPorts |= XTBL_DEBUGPORT_SERIAL; } else if(RTL::WideString::CompareWideStringInsensitive(DebugPort, L"SCREEN", 5) == 0) { /* Enable debug port */ EnabledDebugPorts |= XTBL_DEBUGPORT_SCREEN; } else { /* Unsupported debug port specified */ Console::Print(L"ERROR: Unsupported debug port ('%S') specified\n", DebugPort); EfiUtils::SleepExecution(3000); } /* Take next debug port */ DebugPort = RTL::WideString::TokenizeWideString(NULLPTR, L";", &LastPort); } /* Check if serial debug port is enabled */ if(EnabledDebugPorts & XTBL_DEBUGPORT_SERIAL) { /* Try to initialize COM port */ Status = InitializeSerialPort(PortNumber, PortAddress, BaudRate); if(Status != STATUS_EFI_SUCCESS) { /* Remove serial debug port, as COM port initialization failed and return */ EnabledDebugPorts &= ~XTBL_DEBUGPORT_SERIAL; return Status; } } } /* Return success */ return STATUS_EFI_SUCCESS; } /** * This routine initializes the serial debug console. * * @param PortNumber * Supplies a port number. * * @param PortAddress * Supplies an address of the COM port. * * @param BaudRate * Supplies an optional port baud rate. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Debug::InitializeSerialPort(IN ULONG PortNumber, IN ULONG PortAddress, IN ULONG BaudRate) { EFI_STATUS EfiStatus; XTSTATUS Status; /* Check if custom COM port address supplied */ if(!PortAddress) { /* We support only a pre-defined number of ports */ if(PortNumber > COMPORT_COUNT) { /* Fail if wrong/unsupported port used */ return STATUS_INVALID_PARAMETER; } /* Check if serial port is set */ if(PortNumber == 0) { /* Use COM1 by default */ PortNumber = 1; } /* Set custom port address based on the port number and print debug message */ PortAddress = ComPortList[PortNumber - 1]; Console::Print(L"Initializing serial console at port COM%d\n", PortNumber); } else { /* Custom port address supplied, print debug message */ Console::Print(L"Initializing serial console at COM port address: 0x%lX\n", PortAddress); } /* Initialize COM port */ Status = HL::ComPort::InitializeComPort(&SerialPort, (PUCHAR)UlongToPtr(PortAddress), BaudRate); /* Port not found under supplied address */ if(Status == STATUS_NOT_FOUND && PortAddress) { /* This might be PCI(E) serial controller, try to activate I/O space access first */ EfiStatus = ActivateSerialIOController(); if(EfiStatus == STATUS_EFI_SUCCESS) { /* Try to reinitialize COM port */ Console::Print(L"Enabled I/O space access for all PCI(E) serial controllers found\n"); Status = HL::ComPort::InitializeComPort(&SerialPort, (PUCHAR)UlongToPtr(PortAddress), BaudRate); } } /* Check COM port initialization status code */ if(Status != STATUS_SUCCESS) { /* Serial port initialization failed, mark as not ready */ return STATUS_EFI_NOT_READY; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * This routine formats the input string and prints it out to the debug ports. * * @param Format * The formatted string that is to be written to the output. * * @param ... * Depending on the format string, this routine might expect a sequence of additional arguments. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Debug::Print(IN PCWSTR Format, IN ...) { RTL_PRINT_CONTEXT ConsolePrintContext, SerialPrintContext; VA_LIST Arguments; /* Check if debugging enabled and if EFI serial port is fully initialized */ if(DEBUG) { /* Initialize the print contexts */ ConsolePrintContext.WriteWideCharacter = Console::PutChar; SerialPrintContext.WriteWideCharacter = PutChar; /* Initialise the va_list */ VA_START(Arguments, Format); /* Check if serial debug port is enabled */ if((EnabledDebugPorts & XTBL_DEBUGPORT_SERIAL) && (SerialPort.Flags & COMPORT_FLAG_INIT)) { /* Format and print the string to the serial console */ RTL::WideString::FormatWideString(&SerialPrintContext, (PWCHAR)Format, Arguments); } /* Check if screen debug port is enabled and Boot Services are still available */ if((EnabledDebugPorts & XTBL_DEBUGPORT_SCREEN) && (XtLoader::GetBootServicesStatus() == TRUE)) { /* Format and print the string to the screen */ RTL::WideString::FormatWideString(&ConsolePrintContext, (PWCHAR)Format, Arguments); } /* Clean up the va_list */ VA_END(Arguments); } } /** * Writes a character to the serial console. * * @param Character * The integer promotion of the character to be written. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL XTSTATUS Debug::PutChar(IN WCHAR Character) { WCHAR Buffer[2]; /* Write character to the serial console */ Buffer[0] = Character; Buffer[1] = 0; return HL::ComPort::WriteComPort(&SerialPort, Buffer[0]); } /** * Determines if the serial port has been successfully initialized and is ready for communication. * * @return This routine returns TRUE if the serial port is initialized and ready, FALSE otherwise. * * @since XT 1.0 */ XTCDECL BOOLEAN Debug::SerialPortReady() { return (SerialPort.Flags & COMPORT_FLAG_INIT); } ================================================ FILE: boot/xtldr/efiutils.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/efiutils.cc * DESCRIPTION: EFI related routines for XT Boot Loader * DEVELOPERS: Rafal Kupiec */ #include /** * Reboots into UEFI firmware setup interface. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS EfiUtils::EnterFirmwareSetup() { EFI_GUID Guid = EFI_GLOBAL_VARIABLE_GUID; PULONGLONG SetupSupport = NULLPTR; ULONGLONG Indications; EFI_STATUS Status; /* Check if booting into firmware interface is supported */ Status = GetEfiVariable(&Guid, L"OsIndicationsSupported", (PVOID*)&SetupSupport); if(Status != STATUS_EFI_SUCCESS || !(*SetupSupport & EFI_OS_INDICATIONS_BOOT_TO_FW_UI)) { /* Reboot into firmware setup is not supported */ Debug::Print(L"WARNING: Reboot into firmware setup interface not supported\n"); if(SetupSupport) { Memory::FreePool((PVOID)SetupSupport); } return STATUS_EFI_UNSUPPORTED; } Memory::FreePool((PVOID)SetupSupport); /* Get the value of OsIndications variable */ Indications = 0; Status = GetEfiVariable(&Guid, L"OsIndications", (PVOID*)&Indications); /* Enable FW setup on next boot */ Indications |= EFI_OS_INDICATIONS_BOOT_TO_FW_UI; Status = SetEfiVariable(&Guid, L"OsIndications", (PVOID)&Indications, sizeof(Indications)); if(Status != STATUS_EFI_SUCCESS) { /* Failed to update OsIndications variable */ return Status; } /* Reboot into firmware setup */ RebootSystem(); /* Must not reach this point, just make the compiler happy */ return STATUS_EFI_SUCCESS; } /** * Exits EFI boot services. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS EfiUtils::ExitBootServices() { PEFI_MEMORY_MAP MemoryMap; EFI_STATUS Status; ULONG Counter; /* Boot Services might be partially shutdown, so mark them as unavailable */ XtLoader::DisableBootServices(); /* Allocate buffer for EFI memory map */ Status = Memory::AllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ Debug::Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status); return Status; } /* Zero fill the buffer and initialize counter */ RTL::Memory::ZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP)); Counter = 0xFF; /* Attempt to exit boot services */ while(Counter > 0) { /* Get memory map each time as it can change between two calls */ Status = Memory::GetMemoryMap(MemoryMap); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get new memory map */ return Status; } /* Exit boot services */ Status = XtLoader::GetEfiSystemTable()->BootServices->ExitBootServices(XtLoader::GetEfiImageHandle(), MemoryMap->MapKey); if(Status == STATUS_EFI_SUCCESS) { break; } /* Decrement counter */ Counter--; } /* Return EFI status code */ return Status; } /** * Gets the address of a reqested system configuration table. * * @param TableGuid * Supplies a GUID of the configuration table. * * @param Table * Supplies a pointer to the memory area where the table address will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS EfiUtils::GetConfigurationTable(IN PEFI_GUID TableGuid, OUT PVOID *Table) { SIZE_T Index; /* Iterate through all system configuration tables */ for(Index = 0; Index < XtLoader::GetEfiSystemTable()->NumberOfTableEntries; Index++) { /* Check if this table matches requested table */ if(RTL::Guid::CompareGuids((PGUID)&(XtLoader::GetEfiSystemTable()->ConfigurationTable[Index].VendorGuid), (PGUID)TableGuid)) { /* Found requested table, return success */ *Table = XtLoader::GetEfiSystemTable()->ConfigurationTable[Index].VendorTable; return STATUS_EFI_SUCCESS; } } /* Table not found */ *Table = NULLPTR; return STATUS_EFI_NOT_FOUND; } /** * Gets the value of the EFI variable. * * @param Vendor * Supplies a pointer to the unique vendor GUID. * * @param VariableName * Supplies a pointer to tge NULL-terminated string containing the variable name. * * @param VariableValue * Supplies a pointer to the buffer, where the variable value will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS EfiUtils::GetEfiVariable(IN PEFI_GUID Vendor, IN PCWSTR VariableName, OUT PVOID *VariableValue) { EFI_STATUS Status; PVOID Buffer; UINT_PTR Size = 0; /* Allocate a buffer for storing a variable's value */ Size = EFI_MAXIMUM_VARIABLE_SIZE * sizeof(PWCHAR); Status = Memory::AllocatePool(Size, (PVOID*)&Buffer); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Attempt to get variable value */ Status = XtLoader::GetEfiSystemTable()->RuntimeServices->GetVariable((PWCHAR)VariableName, Vendor, NULLPTR, &Size, Buffer); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get variable, probably not found such one */ return Status; } /* Get variable value and return success */ *VariableValue = Buffer; return STATUS_EFI_SUCCESS; } /** * Returns a random value based on the initialized RNG buffer. * * @param RNGBuffer * Supplies a pointer to the RNG buffer. * * @return This routine returns a random value. * * @since XT 1.0 * * @see https://en.wikipedia.org/wiki/Xorshift */ XTCDECL ULONGLONG EfiUtils::GetRandomValue(IN OUT PULONGLONG RNGBuffer) { /* Recalculate RNG buffer with XORSHIFT */ *RNGBuffer ^= *RNGBuffer >> 12; *RNGBuffer ^= *RNGBuffer << 25; *RNGBuffer ^= *RNGBuffer >> 27; /* Return random value */ return *RNGBuffer * 0x2545F4914F6CDD1D; } /** * Checks whether SecureBoot is enabled or not. * * @return Numeric representation of SecureBoot status (0 = Disabled, >0 = Enabled, <0 SetupMode). * * @since XT 1.0 */ XTCDECL INT_PTR EfiUtils::GetSecureBootStatus() { EFI_GUID VarGuid = EFI_GLOBAL_VARIABLE_GUID; INT_PTR SecureBootStatus = 0; INT_PTR VarValue = 0; UINT_PTR Size; Size = sizeof(INT_PTR); if(XtLoader::GetEfiSystemTable()->RuntimeServices->GetVariable((PWCHAR)L"SecureBoot", &VarGuid, NULLPTR, &Size, &VarValue) == STATUS_EFI_SUCCESS) { SecureBootStatus = VarValue; Size = sizeof(INT_PTR); if((XtLoader::GetEfiSystemTable()->RuntimeServices->GetVariable((PWCHAR)L"SetupMode", &VarGuid, NULLPTR, &Size, &VarValue) == STATUS_EFI_SUCCESS) && VarValue != 0) { SecureBootStatus = -1; } } /* Return SecureBoot status */ return SecureBootStatus; } /** * Initializes the RNG buffer with random bytes from the default EFI RNG algorithm. * * @param RNGBuffer * Supplies a pointer to the RNG buffer. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS EfiUtils::InitializeEntropy(PULONGLONG RNGBuffer) { EFI_GUID RngGuid = EFI_RNG_PROTOCOL_GUID; PEFI_RNG_PROTOCOL Rng; EFI_STATUS Status; ULONGLONG Seed; /* Initialize variables */ Rng = NULLPTR; Seed = 0; /* Locate RNG protocol */ Status = XtLoader::GetEfiSystemTable()->BootServices->LocateProtocol(&RngGuid, NULLPTR, (PVOID *)&Rng); if(Status != STATUS_EFI_SUCCESS) { /* Failed to locate RNG protocol, return status code */ return Status; } /* Get RNG value using the default algorithm */ Status = Rng->GetRNG(Rng, NULLPTR, 8, (PUCHAR)&Seed); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get RNG value, return status code */ return Status; } /* Initialize RNG state and return success */ *RNGBuffer = Seed ? Seed : 1; return STATUS_EFI_SUCCESS; } /** * Loads an EFI image into memory. * * @param DevicePath * Specifies a device path from which the image is loaded. * * @param ImageData * Supplies a pointer to the memory are containing a copy of the EFI image. * * @param ImageSize * Supplies the size (in bytes) of the EFI image. * * @param ImageHandle * Supplies a pointer to the memory area, where an EFI_image handle will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS EfiUtils::LoadEfiImage(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, IN PVOID ImageData, IN SIZE_T ImageSize, OUT PEFI_HANDLE ImageHandle) { /* Load EFI image */ return XtLoader::GetEfiSystemTable()->BootServices->LoadImage(FALSE, XtLoader::GetEfiImageHandle(), DevicePath, ImageData, ImageSize, ImageHandle); } /** * Reboots the machine. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS EfiUtils::RebootSystem() { /* Reboot machine */ return XtLoader::GetEfiSystemTable()->RuntimeServices->ResetSystem(EfiResetCold, STATUS_EFI_SUCCESS, 0, NULLPTR); } /** * Sets a value of an EFI variable. * * @param Vendor * Supplies a pointer to the unique vendor GUID. * * @param VariableName * Supplies a pointer to tge NULL-terminated string containing the variable name. * * @param VariableValue * Supplies the contents of the variable. * * @param Size * Supplies the size of the variable data buffer. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS EfiUtils::SetEfiVariable(IN PEFI_GUID Vendor, IN PCWSTR VariableName, IN PVOID VariableValue, IN UINT_PTR Size) { ULONG Attributes; /* Set EFI variable */ Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; return XtLoader::GetEfiSystemTable()->RuntimeServices->SetVariable((PWCHAR)VariableName, Vendor, Attributes, Size, VariableValue); } /** * Shuts down the machine. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS EfiUtils::ShutdownSystem() { /* Shutdown machine */ return XtLoader::GetEfiSystemTable()->RuntimeServices->ResetSystem(EfiResetShutdown, STATUS_EFI_SUCCESS, 0, NULLPTR); } /** * Puts the system to sleep for the specified number of milliseconds. * * @param Milliseconds * Supplies the number of milliseconds to sleep. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID EfiUtils::SleepExecution(IN ULONG_PTR Milliseconds) { XtLoader::GetEfiSystemTable()->BootServices->Stall(Milliseconds * 1000); } /** * Executes a loaded EFI image entry point. * * @param ImageHandle * Provides a handle of loaded image, that will be started. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS EfiUtils::StartEfiImage(IN EFI_HANDLE ImageHandle) { return XtLoader::GetEfiSystemTable()->BootServices->StartImage(ImageHandle, NULLPTR, NULLPTR); } /** * Waits for one or more EFI events. * * @param NumberOfEvents * Supplies the number of events to wait for. * * @param Event * Supplies the array of events to wait for. * * @param Index * Receives the index of the event that was signaled. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS EfiUtils::WaitForEfiEvent(IN UINT_PTR NumberOfEvents, IN PEFI_EVENT Event, OUT PUINT_PTR Index) { return XtLoader::GetEfiSystemTable()->BootServices->WaitForEvent(NumberOfEvents, Event, Index); } ================================================ FILE: boot/xtldr/includes/libxtos.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/includes/libxtos.hh * DESCRIPTION: XT Loader to LIBXTOS interface * DEVELOPERS: Aiken Harris */ #ifndef __XTLDR_LIBXTOS_HH #define __XTLDR_LIBXTOS_HH #include /* Minimal forward references for AR classes used by XTLDR */ namespace AR { class CpuFunctions { public: STATIC XTCDECL BOOLEAN CpuId(IN OUT PCPUID_REGISTERS Registers); STATIC XTCDECL ULONG_PTR ReadControlRegister(IN USHORT ControlRegister); STATIC XTCDECL ULONGLONG ReadModelSpecificRegister(IN ULONG Register); STATIC XTCDECL VOID WriteControlRegister(IN USHORT ControlRegister, IN UINT_PTR Value); }; class ProcessorSupport { public: STATIC XTAPI VOID GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType, OUT PVOID *TrampolineCode, OUT PULONG_PTR TrampolineSize); }; } /* Minimal forward references for HL classes used by XTLDR */ namespace HL { class ComPort { public: STATIC XTCDECL XTSTATUS InitializeComPort(IN OUT PCPPORT Port, IN PUCHAR PortAddress, IN ULONG BaudRate); STATIC XTCDECL XTSTATUS WriteComPort(IN PCPPORT Port, IN UCHAR Byte); }; class IoPort { public: STATIC XTCDECL UCHAR ReadPort8(IN USHORT Port); STATIC XTCDECL USHORT ReadPort16(IN USHORT Port); STATIC XTCDECL ULONG ReadPort32(IN USHORT Port); STATIC XTCDECL VOID WritePort8(IN USHORT Port, IN UCHAR Value); STATIC XTCDECL VOID WritePort16(IN USHORT Port, IN USHORT Value); STATIC XTCDECL VOID WritePort32(IN USHORT Port, IN ULONG Value); }; } /* Minimal forward references for RTL classes used by XTLDR */ namespace RTL { class Guid { public: STATIC XTAPI BOOLEAN CompareGuids(IN PGUID Guid1, IN PGUID Guid2); }; class LinkedList { public: STATIC XTCDECL VOID InitializeListHead(IN PLIST_ENTRY ListHead); STATIC XTCDECL VOID InsertHeadList(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); STATIC XTCDECL VOID InsertTailList(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); STATIC XTCDECL VOID RemoveEntryList(IN PLIST_ENTRY Entry); }; class Memory { public: STATIC XTAPI SIZE_T CompareMemory(IN PCVOID LeftBuffer, IN PCVOID RightBuffer, IN SIZE_T Length); STATIC XTAPI VOID CopyMemory(OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length); STATIC XTAPI VOID MoveMemory(OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length); STATIC XTAPI VOID SetMemory(OUT PVOID Destination, IN UCHAR Byte, IN SIZE_T Length); STATIC XTAPI VOID ZeroMemory(OUT PVOID Destination, IN SIZE_T Length); }; class String { public: STATIC XTAPI SIZE_T CompareString(IN PCSTR String1, IN PCSTR String2, IN SIZE_T Length); STATIC XTAPI SIZE_T StringLength(IN PCSTR String, IN SIZE_T MaxLength); STATIC XTAPI SIZE_T StringToWideString(OUT PWCHAR Destination, IN PCSTR *Source, IN SIZE_T Length); STATIC XTAPI PCHAR TrimString(IN PCHAR String); }; class WideString { public: STATIC XTAPI SIZE_T CompareWideString(IN PCWSTR String1, IN PCWSTR String2, IN SIZE_T Length); STATIC XTAPI SIZE_T CompareWideStringInsensitive(IN PCWSTR String1, IN PCWSTR String2, IN SIZE_T Length); STATIC XTAPI PWCHAR ConcatenateWideString(OUT PWCHAR Destination, IN PWCHAR Source, IN SIZE_T Count); STATIC XTAPI XTSTATUS FormatWideString(IN PRTL_PRINT_CONTEXT Context, IN PCWSTR Format, IN VA_LIST ArgumentList); STATIC XTAPI PWCHAR TokenizeWideString(IN PWCHAR String, IN PCWSTR Delimiter, IN OUT PWCHAR *SavePtr); STATIC XTAPI SIZE_T WideStringLength(IN PCWSTR String, IN SIZE_T MaxLength); }; } #endif /* __XTLDR_LIBXTOS_HH */ ================================================ FILE: boot/xtldr/includes/xtldr.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/includes/xtldr.hh * DESCRIPTION: Top level header for XTLDR * DEVELOPERS: Rafal Kupiec */ #ifndef __XTLDR_XTLDR_HH #define __XTLDR_XTLDR_HH #include #include #include class BiosUtils { private: STATIC USHORT CursorX; STATIC USHORT CursorY; STATIC CONST USHORT VgaHeight; STATIC CONST USHORT VgaWidth; public: STATIC XTCDECL VOID ClearScreen(); STATIC XTCDECL VOID Print(IN PCWSTR Format, IN ...); STATIC XTCDECL XTSTATUS PutChar(IN WCHAR Character); private: STATIC XTCDECL VOID ScrollScreen(); STATIC XTCDECL VOID UpdateCursor(); }; class BootUtils { public: STATIC XTCDECL BOOLEAN GetBooleanParameter(IN PCWSTR Parameters, IN PCWSTR Needle); }; class Configuration { private: STATIC PLIST_ENTRY BootMenuList; STATIC LIST_ENTRY Config; STATIC LIST_ENTRY ConfigSections; STATIC PCWSTR EditableConfigOptions[]; public: STATIC XTCDECL BOOLEAN GetBooleanValue(IN PCWSTR ConfigName); STATIC XTCDECL EFI_STATUS GetBootOptionValue(IN PLIST_ENTRY Options, IN PCWSTR OptionName, OUT PWCHAR *OptionValue); STATIC XTCDECL VOID GetEditableOptions(OUT PCWSTR **OptionsArray, OUT PULONG OptionsCount); STATIC XTCDECL EFI_STATUS GetValue(IN PCWSTR ConfigName, OUT PWCHAR *ConfigValue); STATIC XTCDECL EFI_STATUS InitializeBootMenuList(IN ULONG MaxNameLength, OUT PXTBL_BOOTMENU_ITEM *MenuEntries, OUT PULONG EntriesCount, OUT PULONG DefaultId); STATIC XTCDECL VOID InitializeConfiguration(); STATIC XTCDECL EFI_STATUS LoadConfiguration(); STATIC XTCDECL EFI_STATUS ParseCommandLine(); STATIC XTCDECL EFI_STATUS SetBootOptionValue(IN PLIST_ENTRY Options, IN PCWSTR OptionName, IN PCWSTR OptionValue); private: STATIC XTCDECL EFI_STATUS ParseConfigFile(IN CONST PCHAR RawConfig, OUT PLIST_ENTRY Configuration); STATIC XTCDECL EFI_STATUS ReadConfigFile(IN PCWSTR ConfigDirectory, IN PCWSTR ConfigFile, OUT PCHAR *ConfigData); STATIC XTCDECL EFI_STATUS SetValue(IN PCWSTR ConfigName, IN PCWSTR ConfigValue); STATIC XTCDECL VOID UpdateConfiguration(IN PLIST_ENTRY NewConfig); }; class Console { public: STATIC XTCDECL VOID ClearLine(IN ULONGLONG LineNo); STATIC XTCDECL VOID ClearScreen(); STATIC XTCDECL VOID DisableCursor(); STATIC XTCDECL VOID EnableCursor(); STATIC XTCDECL VOID InitializeConsole(); STATIC XTCDECL VOID Print(IN PCWSTR Format, IN ...); STATIC XTCDECL XTSTATUS PutChar(IN WCHAR Character); STATIC XTCDECL VOID QueryMode(OUT PUINT_PTR ResX, OUT PUINT_PTR ResY); STATIC XTCDECL EFI_STATUS ReadKeyStroke(OUT PEFI_INPUT_KEY Key); STATIC XTCDECL VOID ResetInputBuffer(); STATIC XTCDECL VOID SetAttributes(IN ULONGLONG Attributes); STATIC XTCDECL VOID SetCursorPosition(IN ULONGLONG PosX, IN ULONGLONG PosY); STATIC XTCDECL VOID Write(IN PCWSTR String); private: STATIC XTCDECL EFI_STATUS SetMode(IN ULONGLONG Mode); }; class Debug { private: STATIC ULONG ComPortList[COMPORT_COUNT]; STATIC ULONG EnabledDebugPorts; STATIC CPPORT SerialPort; public: STATIC XTCDECL EFI_STATUS InitializeDebugConsole(); STATIC XTCDECL VOID Print(IN PCWSTR Format, IN ...); STATIC XTCDECL XTSTATUS PutChar(IN WCHAR Character); STATIC XTCDECL BOOLEAN SerialPortReady(); private: STATIC XTCDECL EFI_STATUS ActivateSerialIOController(); STATIC XTCDECL EFI_STATUS InitializeSerialPort(IN ULONG PortNumber, IN ULONG PortAddress, IN ULONG BaudRate); }; class EfiUtils { public: STATIC XTCDECL EFI_STATUS EnterFirmwareSetup(); STATIC XTCDECL EFI_STATUS ExitBootServices(); STATIC XTCDECL EFI_STATUS GetConfigurationTable(IN PEFI_GUID TableGuid, OUT PVOID *Table); STATIC XTCDECL EFI_STATUS GetEfiVariable(IN PEFI_GUID Vendor, IN PCWSTR VariableName, OUT PVOID *VariableValue); STATIC XTCDECL ULONGLONG GetRandomValue(IN OUT PULONGLONG RNGBuffer); STATIC XTCDECL INT_PTR GetSecureBootStatus(); STATIC XTCDECL EFI_STATUS InitializeEntropy(PULONGLONG RNGBuffer); STATIC XTCDECL EFI_STATUS LoadEfiImage(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, IN PVOID ImageData, IN SIZE_T ImageSize, OUT PEFI_HANDLE ImageHandle); STATIC XTCDECL EFI_STATUS RebootSystem(); STATIC XTCDECL EFI_STATUS SetEfiVariable(IN PEFI_GUID Vendor, IN PCWSTR VariableName, IN PVOID VariableValue, IN UINT_PTR Size); STATIC XTCDECL EFI_STATUS ShutdownSystem(); STATIC XTCDECL VOID SleepExecution(IN ULONG_PTR Milliseconds); STATIC XTCDECL EFI_STATUS StartEfiImage(IN EFI_HANDLE ImageHandle); STATIC XTCDECL EFI_STATUS WaitForEfiEvent(IN UINT_PTR NumberOfEvents, IN PEFI_EVENT Event, OUT PUINT_PTR Index); }; class Memory { public: STATIC XTCDECL EFI_STATUS AllocatePages(IN EFI_ALLOCATE_TYPE AllocationType, IN ULONGLONG NumberOfPages, OUT PEFI_PHYSICAL_ADDRESS Memory); STATIC XTCDECL EFI_STATUS AllocatePool(IN UINT_PTR Size, OUT PVOID *Memory); STATIC XTCDECL EFI_STATUS BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR SelfMapAddress); STATIC XTCDECL EFI_STATUS CommitPageMap(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL EFI_STATUS FreePages(IN ULONGLONG NumberOfPages, IN EFI_PHYSICAL_ADDRESS Memory); STATIC XTCDECL EFI_STATUS FreePool(IN PVOID Memory); STATIC XTCDECL VOID GetMappingsCount(IN PXTBL_PAGE_MAPPING PageMap, OUT PULONG NumberOfMappings); STATIC XTCDECL EFI_STATUS GetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap); STATIC XTCDECL PVOID GetVirtualAddress(IN PXTBL_PAGE_MAPPING PageMap, IN PVOID PhysicalAddress); STATIC XTCDECL VOID InitializePageMap(OUT PXTBL_PAGE_MAPPING PageMap, IN SHORT PageMapLevel, IN PAGE_SIZE PageSize); STATIC XTCDECL EFI_STATUS MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, IN OUT PVOID *BaseAddress, IN BOOLEAN IdentityMapping, IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine); STATIC XTCDECL EFI_STATUS MapPage(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages); STATIC XTCDECL EFI_STATUS MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); STATIC XTCDECL PVOID PhysicalAddressToVirtual(IN PVOID PhysicalAddress, IN PVOID PhysicalBase, IN PVOID VirtualBase); STATIC XTCDECL EFI_STATUS PhysicalListToVirtual(IN PXTBL_PAGE_MAPPING PageMap, IN OUT PLIST_ENTRY ListHead, IN PVOID PhysicalBase, IN PVOID VirtualBase); private: STATIC XTCDECL LOADER_MEMORY_TYPE GetLoaderMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); STATIC XTCDECL EFI_STATUS GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, IN PVOID PageTable, IN SIZE_T Entry, OUT PVOID *NextPageTable); STATIC XTCDECL EFI_STATUS SelfMapPml(IN PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR SelfMapAddress); }; class Protocol { private: STATIC LIST_ENTRY BootProtocols; STATIC XTBL_LOADER_PROTOCOL LoaderProtocol; STATIC LIST_ENTRY LoadedModules; public: STATIC XTCDECL EFI_STATUS CloseProtocol(IN PEFI_HANDLE Handle, IN PEFI_GUID ProtocolGuid); STATIC XTCDECL EFI_STATUS FindBootProtocol(IN PCWSTR SystemType, OUT PEFI_GUID BootProtocolGuid); STATIC XTCDECL PLIST_ENTRY GetModulesList(); STATIC XTCDECL EFI_STATUS InstallProtocol(IN PVOID Interface, IN PEFI_GUID Guid); STATIC XTCDECL VOID InitializeProtocol(); STATIC XTCDECL EFI_STATUS InvokeBootProtocol(IN PWCHAR ShortName, IN PLIST_ENTRY OptionsList); STATIC XTCDECL EFI_STATUS LoadModule(IN PWCHAR ModuleName); STATIC XTCDECL EFI_STATUS LoadModules(IN PWCHAR ModulesList); STATIC XTCDECL EFI_STATUS LocateProtocolHandles(OUT PEFI_HANDLE *Handles, OUT PUINT_PTR Count, IN PEFI_GUID ProtocolGuid); STATIC XTCDECL EFI_STATUS OpenProtocol(OUT PEFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); STATIC XTCDECL EFI_STATUS OpenProtocolHandle(IN EFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); STATIC XTCDECL EFI_STATUS RegisterBootProtocol(IN PCWSTR SystemType, IN PEFI_GUID BootProtocolGuid); STATIC XTCDECL EFI_STATUS InstallXtLoaderProtocol(); private: STATIC XTCDECL EFI_STATUS GetModuleInformation(IN PWCHAR SectionData, IN ULONG SectionSize, OUT PXTBL_MODULE_INFO ModuleInfo); STATIC XTCDECL EFI_STATUS GetModuleInfoStrings(IN PWCHAR SectionData, IN ULONG SectionSize, OUT PWCHAR **ModInfo, OUT PULONG InfoCount); }; class Shell { private: STATIC BOOLEAN ExitRequest; STATIC WCHAR History[XTBL_SH_HISTORY_ENTRIES][XTBL_SH_MAX_LINE_LENGTH]; STATIC ULONG HistoryCount; STATIC ULONG HistoryIndex; STATIC LIST_ENTRY ShellCommands; public: STATIC XTCDECL EFI_STATUS RegisterCommand(IN PCWSTR Command, IN PCWSTR Description, IN PBL_SHELL_COMMAND Handler); STATIC XTCDECL VOID StartLoaderShell(); private: STATIC XTCDECL VOID CommandExit(IN ULONG Argc, IN PWCHAR *Argv); STATIC XTCDECL VOID CommandHelp(IN ULONG Argc, IN PWCHAR *Argv); STATIC XTCDECL VOID CommandInsmod(IN ULONG Argc, IN PWCHAR *Argv); STATIC XTCDECL VOID CommandLsmod(IN ULONG Argc, IN PWCHAR *Argv); STATIC XTCDECL VOID CommandPoweroff(IN ULONG Argc, IN PWCHAR *Argv); STATIC XTCDECL VOID CommandReboot(IN ULONG Argc, IN PWCHAR *Argv); STATIC XTCDECL VOID CommandVersion(IN ULONG Argc, IN PWCHAR *Argv); STATIC XTCDECL VOID ExecuteCommand(IN ULONG Argc, IN PWCHAR *Argv); STATIC XTCDECL EFI_STATUS ParseCommand(IN PWCHAR CommandLine, OUT PULONG Argc, OUT PWCHAR **Argv); STATIC XTCDECL VOID PrintPrompt(); STATIC XTCDECL VOID PrintPromptLine(IN PWCHAR Buffer, IN ULONG BufferLength, IN ULONG CursorPosition, IN ULONG PreviousBufferLength); STATIC XTCDECL VOID ReadCommand(OUT PWCHAR Buffer, IN ULONG BufferSize); STATIC XTCDECL VOID RegisterBuiltinCommands(); }; class TextUi { public: STATIC XTCDECL VOID DisplayBootMenu(); STATIC XTCDECL VOID DisplayErrorDialog(IN PCWSTR Caption, IN PCWSTR Message); STATIC XTCDECL VOID DisplayInfoDialog(IN PCWSTR Caption, IN PCWSTR Message); STATIC XTCDECL VOID DisplayInputDialog(IN PCWSTR Caption, IN PCWSTR Message, IN OUT PWCHAR *InputFieldText); STATIC XTCDECL XTBL_DIALOG_HANDLE DisplayProgressDialog(IN PCWSTR Caption, IN PCWSTR Message, IN UCHAR Percentage); STATIC XTCDECL VOID UpdateProgressBar(IN PXTBL_DIALOG_HANDLE Handle, IN PCWSTR Message, IN UCHAR Percentage); private: STATIC XTCDECL VOID DetermineDialogBoxSize(IN OUT PXTBL_DIALOG_HANDLE Handle, IN PCWSTR Message); STATIC XTCDECL VOID DisplayEditMenu(IN PXTBL_BOOTMENU_ITEM MenuEntry); STATIC XTCDECL VOID DrawBootMenu(OUT PXTBL_DIALOG_HANDLE Handle); STATIC XTCDECL VOID DrawBootMenuEntry(IN PXTBL_DIALOG_HANDLE Handle, IN PWCHAR MenuEntry, IN UINT Position, IN BOOLEAN Highlighted); STATIC XTCDECL VOID DrawDialogBox(IN OUT PXTBL_DIALOG_HANDLE Handle, IN PCWSTR Caption, IN PCWSTR Message); STATIC XTCDECL VOID DrawButton(IN PXTBL_DIALOG_HANDLE Handle); STATIC XTCDECL VOID DrawInputField(IN PXTBL_DIALOG_HANDLE Handle, IN PWCHAR InputFieldText); STATIC XTCDECL VOID DrawMessage(IN PXTBL_DIALOG_HANDLE Handle, IN PCWSTR Message); STATIC XTCDECL VOID DrawProgressBar(IN PXTBL_DIALOG_HANDLE Handle, IN UCHAR Percentage); STATIC XTCDECL VOID DrawEditMenu(OUT PXTBL_DIALOG_HANDLE Handle); STATIC XTCDECL EFI_STATUS DrawEditMenuEntry(IN PXTBL_DIALOG_HANDLE Handle, IN PCWSTR OptionName, IN PCWSTR OptionValue, IN UINT Position, IN BOOLEAN Highlighted); }; class Volume { private: STATIC LIST_ENTRY EfiBlockDevices; public: STATIC XTCDECL EFI_STATUS CloseVolume(IN PEFI_HANDLE VolumeHandle); STATIC XTCDECL EFI_STATUS EnumerateBlockDevices(); STATIC XTCDECL EFI_STATUS FindDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL FsHandle, IN CONST PWCHAR FileSystemPath, OUT PEFI_DEVICE_PATH_PROTOCOL* DevicePath); STATIC XTCDECL EFI_STATUS GetEfiPath(IN PWCHAR SystemPath, OUT PWCHAR *EfiPath); STATIC XTCDECL EFI_STATUS GetDevicePath(IN PWCHAR SystemPath, OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT PWCHAR *ArcName, OUT PWCHAR *Path); STATIC XTCDECL EFI_STATUS OpenVolume(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_HANDLE DiskHandle, OUT PEFI_FILE_HANDLE *FsHandle); STATIC XTCDECL EFI_STATUS ReadFile(IN PEFI_FILE_HANDLE DirHandle, IN PCWSTR FileName, OUT PVOID *FileData, OUT PSIZE_T FileSize); private: STATIC XTCDECL EFI_STATUS DiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices); STATIC XTCDECL EFI_STATUS DissectArcPath(IN PWCHAR SystemPath, OUT PWCHAR *ArcName, OUT PWCHAR *Path, OUT PUSHORT DriveType, OUT PULONG DriveNumber, OUT PULONG PartNumber); STATIC XTCDECL PEFI_DEVICE_PATH_PROTOCOL DuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath); STATIC XTCDECL EFI_STATUS FindLastBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_DEVICE_PATH_PROTOCOL *LastNode); STATIC XTCDECL BOOLEAN FindParentBlockDevice(IN PLIST_ENTRY BlockDevices, IN PEFI_BLOCK_DEVICE_DATA ChildNode, OUT PEFI_BLOCK_DEVICE_DATA *ParentNode); }; class XtLoader { private: STATIC PBL_XT_BOOT_MENU BootMenu; STATIC EFI_HANDLE EfiImageHandle; STATIC PEFI_SYSTEM_TABLE EfiSystemTable; STATIC XTBL_STATUS LoaderStatus; public: STATIC XTCDECL VOID DisableBootServices(); STATIC XTCDECL BOOLEAN GetBootServicesStatus(); STATIC XTCDECL EFI_HANDLE GetEfiImageHandle(); STATIC XTCDECL PEFI_SYSTEM_TABLE GetEfiSystemTable(); STATIC XTCDECL VOID GetLoaderImageInformation(PVOID *LoaderBase, PULONGLONG LoaderSize); STATIC XTCDECL INT_PTR GetSecureBootStatus(); STATIC XTCDECL VOID InitializeBootLoader(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable); STATIC XTCDECL VOID RegisterBootMenu(IN PVOID BootMenuRoutine); STATIC XTCDECL VOID ShowBootMenu(); }; #endif /* __XTLDR_XTLDR_HH */ ================================================ FILE: boot/xtldr/library/modproto.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/library/modproto.cc * DESCRIPTION: XT Boot Loader protocol support for XTLDR modules * DEVELOPERS: Rafal Kupiec */ #include /** * Finds and opens the XT Boot Loader protocol. This routine should be called by module to access XTLDR protocol. * * @param SystemTable * Provides the EFI system table. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param ProtocolHandler * Receives the pointer to the XT Boot Loader protocol. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCLINK XTCDECL EFI_STATUS BlGetXtLdrProtocol(IN PEFI_SYSTEM_TABLE SystemTable, IN EFI_HANDLE ImageHandle, OUT PXTBL_LOADER_PROTOCOL *ProtocolHandler) { EFI_GUID ProtocolGuid = XT_BOOT_LOADER_PROTOCOL_GUID; PEFI_HANDLE Handles = NULLPTR; EFI_STATUS Status; UINT_PTR Count; UINT Index; /* Try to locate the handles */ Status = SystemTable->BootServices->LocateHandleBuffer(ByProtocol, &ProtocolGuid, NULLPTR, &Count, &Handles); if(Status != STATUS_EFI_SUCCESS) { /* Unable to get handles */ return Status; } /* Check if any handles returned */ if(Count > 0) { /* Iterate through all given handles */ for(Index = 0; Index < Count; Index++) { /* Try to open protocol */ Status = SystemTable->BootServices->OpenProtocol(Handles[Index], &ProtocolGuid, (PVOID*)ProtocolHandler, ImageHandle, NULLPTR, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); /* Check if successfully opened the loader protocol */ if(Status == STATUS_EFI_SUCCESS) { /* Protocol found and successfully opened */ break; } } } /* Free handles */ SystemTable->BootServices->FreePool(Handles); /* Make sure the loaded protocol has been found */ if(*ProtocolHandler == NULLPTR) { /* Protocol not found */ return STATUS_EFI_NOT_FOUND; } /* Return success */ return STATUS_EFI_SUCCESS; } ================================================ FILE: boot/xtldr/memory.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/memory.cc * DESCRIPTION: XT Boot Loader memory management * DEVELOPERS: Rafal Kupiec */ #include /** * This routine allocates one or more 4KB pages. * * @param NumberOfPages * The number of contiguous 4KB pages to allocate. * * @param Memory * The pointer to a physical address. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::AllocatePages(IN EFI_ALLOCATE_TYPE AllocationType, IN ULONGLONG NumberOfPages, OUT PEFI_PHYSICAL_ADDRESS Memory) { return XtLoader::GetEfiSystemTable()->BootServices->AllocatePages(AllocationType, EfiLoaderData, NumberOfPages, Memory); } /** * This routine allocates a pool memory. * * @param Size * The number of bytes to allocate from the pool. * * @param Memory * The pointer to a physical address. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::AllocatePool(IN UINT_PTR Size, OUT PVOID *Memory) { /* Allocate pool */ return XtLoader::GetEfiSystemTable()->BootServices->AllocatePool(EfiLoaderData, Size, Memory); } /** * This routine frees memory pages. * * @param NumberOfPages * The number of contiguous 4 KB pages to free. * * @param Memory * The base physical address of the pages to be freed. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::FreePages(IN ULONGLONG NumberOfPages, IN EFI_PHYSICAL_ADDRESS Memory) { return XtLoader::GetEfiSystemTable()->BootServices->FreePages(Memory, NumberOfPages); } /** * Returns pool memory to the system. * * @param Memory * The pointer to the buffer to free. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::FreePool(IN PVOID Memory) { /* Free pool */ return XtLoader::GetEfiSystemTable()->BootServices->FreePool(Memory); } /** * Converts EFI memory type to XTLDR memory type. * * @param EfiMemoryType * Specifies EFI memory type. * * @return This routine returns a mapped XTLDR memory type. * * @since XT 1.0 */ XTCDECL LOADER_MEMORY_TYPE Memory::GetLoaderMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType) { LOADER_MEMORY_TYPE MemoryType; /* Check EFI memory type and convert to XTLDR memory type */ switch(EfiMemoryType) { case EfiACPIMemoryNVS: case EfiACPIReclaimMemory: case EfiPalCode: case EfiReservedMemoryType: MemoryType = LoaderSpecialMemory; break; case EfiRuntimeServicesCode: case EfiRuntimeServicesData: case EfiMemoryMappedIO: case EfiMemoryMappedIOPortSpace: MemoryType = LoaderFirmwarePermanent; break; case EfiBootServicesData: case EfiLoaderCode: case EfiLoaderData: MemoryType = LoaderFirmwareTemporary; break; case EfiUnusableMemory: MemoryType = LoaderBad; break; default: MemoryType = LoaderFree; break; } /* Return XTLDR memory type */ return MemoryType; } /** * Returns the number of mappings in the page mapping structure. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @param NumberOfMappings * Supplies a pointer to memory area where the number of mappings is returned. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Memory::GetMappingsCount(IN PXTBL_PAGE_MAPPING PageMap, OUT PULONG NumberOfMappings) { /* Return number of mappings */ *NumberOfMappings = PageMap->MapSize; } /** * Returns the memory descriptors which define a memory map of all the physical memory ranges reserved by the UEFI. * * @param MemoryMap * Supplies a pointer to the buffer where memory map will be written. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::GetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap) { EFI_STATUS Status; if(MemoryMap == NULLPTR) { return STATUS_EFI_INVALID_PARAMETER; } MemoryMap->Map = NULLPTR; MemoryMap->MapSize = 0; /* Get memory map */ do { /* Attempt do get EFI memory map */ Status = XtLoader::GetEfiSystemTable()->BootServices->GetMemoryMap(&MemoryMap->MapSize, MemoryMap->Map, &MemoryMap->MapKey, &MemoryMap->DescriptorSize, &MemoryMap->DescriptorVersion); if(Status == STATUS_EFI_SUCCESS) { /* Go further if succeeded */ break; } else if(Status != STATUS_EFI_BUFFER_TOO_SMALL) { /* Some error occurred */ if(MemoryMap->Map) { /* Free allocated memory */ FreePool(MemoryMap->Map); } return Status; } /* Allocate the desired amount of memory */ MemoryMap->MapSize += 2 * MemoryMap->DescriptorSize; AllocatePool(MemoryMap->MapSize, (PVOID *)&MemoryMap->Map); } while(Status == STATUS_EFI_BUFFER_TOO_SMALL); /* Make sure memory map is set */ if(MemoryMap->Map == NULLPTR) { /* Something went wrong */ return STATUS_EFI_NO_MAPPING; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Attempts to find a virtual address of the specified physical address in memory mappings. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @param PhysicalAddress * Supplies a physical address to search for in the mappings. * * @return This routine returns a corresponding virtual address found in the mappings. * * @since XT 1.0 */ XTCDECL PVOID Memory::GetVirtualAddress(IN PXTBL_PAGE_MAPPING PageMap, IN PVOID PhysicalAddress) { PXTBL_MEMORY_MAPPING Mapping; PLIST_ENTRY ListEntry; /* Iterate over memory mappings in order to find descriptor containing a physical address */ ListEntry = PageMap->MemoryMap.Flink; while(ListEntry != &PageMap->MemoryMap) { /* Get mapping from linked list */ Mapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry); /* Make sure any virtual address is set */ if(Mapping->VirtualAddress) { /* Check if provided physical address is in range of this mapping */ if(((UINT_PTR)PhysicalAddress >= (UINT_PTR)Mapping->PhysicalAddress) && ((UINT_PTR)PhysicalAddress < ((UINT_PTR)Mapping->PhysicalAddress + (Mapping->NumberOfPages * EFI_PAGE_SIZE)))) { /* Calculate virtual address based on the mapping and return it */ return (PVOID)(((UINT_PTR)PhysicalAddress - (UINT_PTR)Mapping->PhysicalAddress) + (UINT_PTR)Mapping->VirtualAddress); } } /* Get next element from the list */ ListEntry = ListEntry->Flink; } /* Mapping not found, return 0 */ return 0; } /** * Initializes the page mapping structures. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @param PageMapLevel * Specifies a number of of paging structures levels. * * @param PageSize * Specifies a page size (currently it has no effect). * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Memory::InitializePageMap(OUT PXTBL_PAGE_MAPPING PageMap, IN SHORT PageMapLevel, IN PAGE_SIZE PageSize) { /* Initialize memory mappings */ RTL::LinkedList::InitializeListHead(&PageMap->MemoryMap); PageMap->MapSize = 0; /* Set page map size/level and memory map address */ PageMap->PageMapLevel = PageMapLevel; PageMap->PageSize = PageSize; } /** * Adds EFI memory mapping to the page mapping structure. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @param BaseAddress * Supplies a virtual address, where EFI memory will be mapped. * * @param IdentityMapping * Specifies whether EFI non-free memory should be mapped by identity or sequential mapping. * * @param GetMemoryTypeRoutine * Supplies a pointer to the routine which will be used to match EFI memory type to the OS memory type. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, IN OUT PVOID *BaseAddress, IN BOOLEAN IdentityMapping, IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine) { ULONGLONG MaxAddress, VirtualAddress; PEFI_MEMORY_DESCRIPTOR Descriptor; LOADER_MEMORY_TYPE MemoryType; PEFI_MEMORY_MAP MemoryMap; SIZE_T DescriptorCount; EFI_STATUS Status; SIZE_T Index; /* Set virtual address as specified in argument */ VirtualAddress = (ULONGLONG)*BaseAddress; /* Check if custom memory type routine is specified */ if(GetMemoryTypeRoutine == NULLPTR) { /* Use default memory type routine */ GetMemoryTypeRoutine = GetLoaderMemoryType; } /* Allocate and zero-fill buffer for EFI memory map */ AllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap); RTL::Memory::ZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP)); /* Get EFI memory map */ Status = GetMemoryMap(MemoryMap); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get EFI memory map */ return Status; } /* Calculate descriptors count and get first one */ Descriptor = MemoryMap->Map; DescriptorCount = MemoryMap->MapSize / MemoryMap->DescriptorSize; /* Iterate through all descriptors from the memory map */ for(Index = 0; Index < DescriptorCount; Index++) { /* Check page map level */ if(PageMap->PageMapLevel == 2) { /* Limit physical address to 4GB in legacy mode */ MaxAddress = 0xFFFFFFFF; } else if(PageMap->PageMapLevel == 3) { /* Limit physical address to 64GB in PAE mode */ MaxAddress = 0xFFFFFFFFFULL; } /* Check page map level */ if(PageMap->PageMapLevel == 2 || PageMap->PageMapLevel == 3) { /* Check if physical address starts beyond limit */ if(Descriptor->PhysicalStart >= MaxAddress) { /* Go to the next descriptor */ Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize); continue; } /* Check if memory descriptor exceeds the lowest physical page */ if(Descriptor->PhysicalStart + (Descriptor->NumberOfPages << EFI_PAGE_SHIFT) > MaxAddress) { /* Truncate memory descriptor to the lowest supported physical page */ Descriptor->NumberOfPages = (MaxAddress - Descriptor->PhysicalStart) >> EFI_PAGE_SHIFT; } } { /* Skip EFI reserved memory */ if(Descriptor->Type == EfiReservedMemoryType) { /* Go to the next descriptor */ Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize); continue; } /* Convert EFI memory type into XTLDR memory type */ MemoryType = GetMemoryTypeRoutine((EFI_MEMORY_TYPE)Descriptor->Type); /* Do memory mappings depending on memory type */ if(MemoryType == LoaderFirmwareTemporary) { /* Map EFI firmware code */ Status = MapVirtualMemory(PageMap, Descriptor->PhysicalStart, Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); } else if(MemoryType != LoaderFree) { /* Check mapping strategy */ if(IdentityMapping) { /* Add any non-free memory using identity mapping */ Status = MapVirtualMemory(PageMap, Descriptor->PhysicalStart + KSEG0_BASE, Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); } else { /* Add any non-free memory using sequential mapping */ Status = MapVirtualMemory(PageMap, VirtualAddress, Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); /* Update virtual address */ VirtualAddress = VirtualAddress + (Descriptor->NumberOfPages * MM_PAGE_SIZE); } } else { /* Map all other memory as loader free */ Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Descriptor->PhysicalStart, Descriptor->NumberOfPages, LoaderFree); } /* Make sure memory mapping succeeded */ if(Status != STATUS_EFI_SUCCESS) { /* Mapping failed */ return Status; } } /* Grab next descriptor */ Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize); } /* Always map first page */ Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, 0, 1, LoaderFirmwarePermanent); if(Status != STATUS_EFI_SUCCESS) { /* Mapping failed */ return Status; } /* Map BIOS ROM and VRAM */ Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, 0xA0000, 0x60, LoaderFirmwarePermanent); if(Status != STATUS_EFI_SUCCESS) { /* Mapping failed */ return Status; } /* Store next valid virtual address and return success */ *BaseAddress = (PVOID)VirtualAddress; return STATUS_EFI_SUCCESS; } /** * Adds a physical to virtual address mappings. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @param VirtualAddress * Supplies a virtual address where the physical address should be mapped. * * @param PhysicalAddress * Supplies a physical address which will be mapped. * * @param NumberOfPages * Supplies a number of pages that will be mapped. * * @param MemoryType * Supplies the type of mapped memory that will be assigned to the memory descriptor. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType) { PXTBL_MEMORY_MAPPING Mapping1, Mapping2, Mapping3; ULONGLONG PhysicalAddressEnd, PhysicalAddress2End; PLIST_ENTRY ListEntry, MappingListEntry; SIZE_T NumberOfMappedPages; EFI_STATUS Status; /* Allocate memory for new mapping */ Status = AllocatePool(sizeof(XTBL_MEMORY_MAPPING), (PVOID *)&Mapping1); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Set mapping fields */ Mapping1->PhysicalAddress = PhysicalAddress; Mapping1->VirtualAddress = VirtualAddress; Mapping1->NumberOfPages = NumberOfPages; Mapping1->MemoryType = MemoryType; /* Calculate the end of the physical address */ PhysicalAddressEnd = PhysicalAddress + (NumberOfPages * EFI_PAGE_SIZE) - 1; /* Iterate through all the mappings already set to insert new mapping at the correct place */ ListEntry = PageMap->MemoryMap.Flink; while(ListEntry != &PageMap->MemoryMap) { /* Take a mapping from the list and calculate its end of physical address */ Mapping2 = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry); PhysicalAddress2End = Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1; /* Check if new mapping is a subset of an existing mapping */ if(Mapping1->PhysicalAddress >= Mapping2->PhysicalAddress && PhysicalAddressEnd <= PhysicalAddress2End) { /* Make sure it's memory type is the same */ if(Mapping1->MemoryType == Mapping2->MemoryType) { /* Free the unused mapping structure and return success */ FreePool(Mapping1); return STATUS_EFI_SUCCESS; } } /* Check if they overlap */ if(PhysicalAddressEnd > Mapping2->PhysicalAddress && PhysicalAddressEnd <= PhysicalAddress2End) { /* Make sure it's memory type is LoaderFree */ if(Mapping2->MemoryType != LoaderFree) { /* LoaderFree memory type is strictly expected */ return STATUS_EFI_INVALID_PARAMETER; } /* Calculate number of pages for this mapping */ NumberOfMappedPages = (PhysicalAddress2End - PhysicalAddressEnd) / EFI_PAGE_SIZE; if(NumberOfMappedPages > 0) { /* Pages associated to the mapping, allocate memory for it */ Status = AllocatePool(sizeof(XTBL_MEMORY_MAPPING), (PVOID*)&Mapping3); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Set mapping fields */ Mapping3->PhysicalAddress = PhysicalAddressEnd + 1; Mapping3->VirtualAddress = (ULONGLONG)NULLPTR; Mapping3->NumberOfPages = NumberOfMappedPages; Mapping3->MemoryType = Mapping2->MemoryType; /* Insert new mapping in front of the list and increase page map size */ RTL::LinkedList::InsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry); PageMap->MapSize++; } /* Calculate number of pages and the end of the physical address */ Mapping2->NumberOfPages = ((PUCHAR)PhysicalAddressEnd + 1 - (PUCHAR)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE; PhysicalAddress2End = Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1; } /* Check if they overlap */ if(Mapping1->PhysicalAddress > Mapping2->PhysicalAddress && Mapping1->PhysicalAddress < PhysicalAddress2End) { /* Make sure it's memory type is LoaderFree */ if(Mapping2->MemoryType != LoaderFree) { /* LoaderFree memory type is strictly expected */ return STATUS_EFI_INVALID_PARAMETER; } /* Calculate number of pages for this mapping */ NumberOfMappedPages = ((PUCHAR)PhysicalAddress2End + 1 - (PUCHAR)Mapping1->PhysicalAddress) / EFI_PAGE_SIZE; if(NumberOfMappedPages > 0) { /* Pages associated to the mapping, allocate memory for it */ Status = AllocatePool(sizeof(XTBL_MEMORY_MAPPING), (PVOID*)&Mapping3); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Set mapping fields */ Mapping3->PhysicalAddress = Mapping1->PhysicalAddress; Mapping3->VirtualAddress = (ULONGLONG)NULLPTR; Mapping3->NumberOfPages = NumberOfMappedPages; Mapping3->MemoryType = Mapping2->MemoryType; /* Insert new mapping in front of the list and increase page map size */ RTL::LinkedList::InsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry); PageMap->MapSize++; } /* Calculate number of pages and the end of the physical address */ Mapping2->NumberOfPages = ((PUCHAR)Mapping1->PhysicalAddress - (PUCHAR)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE; PhysicalAddress2End = Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1; } /* Check if mapping is really needed */ if((Mapping2->PhysicalAddress >= Mapping1->PhysicalAddress && PhysicalAddress2End <= PhysicalAddressEnd) || (Mapping2->NumberOfPages == 0)) { /* Make sure it's memory type is LoaderFree */ if(Mapping2->MemoryType != LoaderFree) { /* LoaderFree memory type is strictly expected */ return STATUS_EFI_INVALID_PARAMETER; } /* Store address of the next mapping */ MappingListEntry = ListEntry->Flink; /* Remove mapping from the list and free up it's memory */ RTL::LinkedList::RemoveEntryList(&Mapping2->ListEntry); Status = FreePool(Mapping2); ListEntry = MappingListEntry; /* Decrease page map size and go to the next mapping */ PageMap->MapSize--; continue; } /* Determine physical address order */ if(Mapping2->PhysicalAddress > Mapping1->PhysicalAddress) { /* Insert new mapping in front of the list and increase page map size */ RTL::LinkedList::InsertHeadList(Mapping2->ListEntry.Blink, &Mapping1->ListEntry); PageMap->MapSize++; /* Return success */ return STATUS_EFI_SUCCESS; } /* Get next mapping from the list */ ListEntry = ListEntry->Flink; } /* Insert new mapping to the tail of the list and increase page map size */ RTL::LinkedList::InsertTailList(&PageMap->MemoryMap, &Mapping1->ListEntry); PageMap->MapSize++; /* Return success */ return STATUS_EFI_SUCCESS; } /** * Converts physical address to virtual address based on physical base and virtual base. * * @param PhysicalAddress * Specifies physical address that will be converted to virtual address. * * @param PhysicalBase * Supplies a physical base address. * * @param VirtualBase * Supplies a virtual base address. * * @return This routine returns a mapped virtual address. * * @since XT 1.0 */ XTCDECL PVOID Memory::PhysicalAddressToVirtual(IN PVOID PhysicalAddress, IN PVOID PhysicalBase, IN PVOID VirtualBase) { /* Convert physical address to virtual address */ return (PUCHAR)VirtualBase + ((PUCHAR)PhysicalAddress - (PUCHAR)PhysicalBase); } /** * Converts whole linked list addressing from physical to virtual for future use after enabling paging. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @param ListHead * Supplies a pointer to a structure that serves as the list header. * * @param PhysicalBase * Supplies a physical base address. * * @param VirtualBase * Supplies a virtual base address. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Memory::PhysicalListToVirtual(IN PXTBL_PAGE_MAPPING PageMap, IN OUT PLIST_ENTRY ListHead, IN PVOID PhysicalBase, IN PVOID VirtualBase) { PLIST_ENTRY ListEntry, NextEntry; /* Make sure list is properly initialized */ if(ListHead->Flink == 0 || ListHead->Blink == 0) { /* List not initialized, return error code */ return STATUS_EFI_INVALID_PARAMETER; } /* Iterate through all elements */ ListEntry = ListHead->Flink; while(ListEntry != ListHead) { /* Save physical address of the next element */ NextEntry = ListEntry->Flink; /* Convert the address of this element to VirtualAddress */ if(ListEntry->Blink == ListHead) { /* Find virtual address of list head */ ListEntry->Blink = (PLIST_ENTRY)GetVirtualAddress(PageMap, ListEntry->Blink); } else { /* Convert list entry */ ListEntry->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Blink, (PVOID)PhysicalBase, VirtualBase); } if(ListEntry->Flink == ListHead) { /* Convert list head */ ListEntry->Flink = ListHead->Flink->Blink; } else { /* Convert list entry */ ListEntry->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Flink, (PVOID)PhysicalBase, VirtualBase); } /* Get to the next element*/ ListEntry = NextEntry; } /* Convert list head */ ListHead->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Blink, (PVOID)PhysicalBase, VirtualBase); ListHead->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Flink, (PVOID)PhysicalBase, VirtualBase); /* Return success */ return STATUS_EFI_SUCCESS; } ================================================ FILE: boot/xtldr/modules/CMakeLists.txt ================================================ add_subdirectory(acpi) add_subdirectory(beep) add_subdirectory(chainldr) add_subdirectory(dummy) add_subdirectory(framebuf) add_subdirectory(pecoff) add_subdirectory(xtos_o) ================================================ FILE: boot/xtldr/modules/acpi/CMakeLists.txt ================================================ # XT Boot Loader ACPI Support Module PROJECT(XTLDR_ACPI) # Specify include directories include_directories( ${EXECTOS_SOURCE_DIR}/sdk/xtdk ${XTLDR_ACPI_SOURCE_DIR}/includes) # Specify list of source code files list(APPEND XTLDR_ACPI_SOURCE ${XTLDR_ACPI_SOURCE_DIR}/acpi.cc ${XTLDR_ACPI_SOURCE_DIR}/data.cc) # Link module executable add_executable(acpi ${XTLDR_ACPI_SOURCE}) # Add linker libraries target_link_libraries(acpi libxtldr libxtos) # Set proper binary name and install target set_target_properties(acpi PROPERTIES SUFFIX .efi) set_install_target(acpi efi/boot/xtldr/modules) # Set module entrypoint and subsystem set_entrypoint(acpi "XtLdrModuleMain") set_linker_map(acpi TRUE) set_subsystem(acpi efi_boot_service_driver) ================================================ FILE: boot/xtldr/modules/acpi/acpi.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/acpi/acpi.cc * DESCRIPTION: XTLDR ACPI Support Module * DEVELOPERS: Rafal Kupiec */ #include /* ACPI module information */ MODULE_AUTHOR(L"Rafal Kupiec "); MODULE_DESCRIPTION(L"ACPI support"); MODULE_LICENSE(L"GPLv3"); MODULE_VERSION(L"0.1"); /** * Attempts to get XSDP. If it is not found or checksum mismatch, it will try to get RSDP instead. * * @param AcpiTable * Suplies a pointer to memory area where XSDP or RSRP address will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Acpi::GetAcpiDescriptionPointer(OUT PVOID *AcpiTable) { PVOID Rsdp; /* Try to get XSDP (ACPI 2.0) from system configuration tables */ if(GetXsdpTable(&Rsdp) == STATUS_EFI_SUCCESS) { /* XSDP found, return success */ *AcpiTable = Rsdp; return STATUS_EFI_SUCCESS; } /* Try to get RSDP (ACPI 1.0) from system configuration tables */ if(GetRsdpTable(&Rsdp) == STATUS_EFI_SUCCESS) { /* RSDP found, return success */ *AcpiTable = Rsdp; return STATUS_EFI_SUCCESS; } /* Neither XSDP nor RSDP found */ return STATUS_EFI_NOT_FOUND; } /** * Finds ACPI description table with given signature. * * @param Signature * Supplies the signature of the desired ACPI table. * * @param PreviousTable * Supplies a pointer to the table to start searching from. * * @param AcpiTable * Supplies a pointer to memory area where ACPI table address will be stored, or NULLPTR if not found. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Acpi::GetAcpiTable(IN CONST UINT Signature, IN PVOID PreviousTable, OUT PVOID *AcpiTable) { PACPI_DESCRIPTION_HEADER TableHeader; SIZE_T RsdtIndex, TableIndex; EFI_STATUS Status; SIZE_T TableCount; PACPI_RSDP Rsdp; PACPI_RSDT Rsdt; BOOLEAN Xsdp; /* Return NULLPTR by default if requested table not found */ *AcpiTable = NULLPTR; /* Get Root System Description Table Pointer */ Status = GetAcpiDescriptionPointer((PVOID*)&Rsdp); if(Status != STATUS_EFI_SUCCESS) { /* ACPI tables not found, return error */ return Status; } /* Check if it is XSDP (ACPI 2.0) or RSDP (ACPI 1.0) */ if(Rsdp->Revision >= 2 && Rsdp->XsdtAddress) { /* XSDP (ACPI 2.0) */ Xsdp = TRUE; Rsdt = (PACPI_RSDT)(UINT_PTR)Rsdp->XsdtAddress; TableCount = (Rsdt->Header.Length - sizeof(ACPI_DESCRIPTION_HEADER)) / 8; } else { /* RSDP (ACPI 1.0) */ Xsdp = FALSE; Rsdt = (PACPI_RSDT)(UINT_PTR)Rsdp->RsdtAddress; TableCount = (Rsdt->Header.Length - sizeof(ACPI_DESCRIPTION_HEADER)) / 4; } /* Iterate over all ACPI tables */ for(TableIndex = 0; TableIndex < TableCount; TableIndex++) { /* Get table headers in reverse order */ RsdtIndex = TableCount - TableIndex - 1; /* Check if XSDP or RSDT is used */ if(Xsdp) { /* Get table header from XSDT */ TableHeader = (PACPI_DESCRIPTION_HEADER)(ULONG_PTR)((PULONGLONG)Rsdt->Tables)[RsdtIndex]; } else { /* Get table header from RSDT */ TableHeader = (PACPI_DESCRIPTION_HEADER)(ULONG_PTR)((PULONG)Rsdt->Tables)[RsdtIndex]; } /* Check if previous table provided */ if(PreviousTable != NULLPTR) { /* Check if this is a table previously found */ if(TableHeader == (PVOID)PreviousTable) { /* Unset previous table */ PreviousTable = NULLPTR; } /* Skip to next ACPI table */ continue; } /* Verify table signature */ if((TableHeader->Signature == Signature)) { /* Found requested ACPI table */ break; } } /* Make sure table was found */ if(TableHeader->Signature != Signature) { /* ACPI table not found, return error */ return STATUS_EFI_NOT_FOUND; } /* Don't validate FADT on old, broken firmwares with ACPI 2.0 or older */ if(TableHeader->Signature != ACPI_FADT_SIGNATURE || TableHeader->Revision > 2) { /* Validate table checksum */ if(!ValidateAcpiTable(TableHeader, TableHeader->Length)) { /* Checksum mismatch, return error */ return STATUS_EFI_CRC_ERROR; } } /* Found valid ACPI table, return success */ *AcpiTable = TableHeader; return STATUS_EFI_SUCCESS; } /** * Gets the Advanced Programmable Interrupt Controller (APIC) base address. * * @param ApicBase * Supplies a pointer to memory area where APIC base address will be stored. * * @return This routine returns an EFI status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Acpi::GetApicBase(OUT PVOID *ApicBase) { CPUID_REGISTERS CpuRegisters; /* Prepare CPUID registers to query for APIC support */ XtLdrProtocol->Memory.ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES; /* Query CPUID */ XtLdrProtocol->Cpu.CpuId(&CpuRegisters); /* Check if APIC present */ if((CpuRegisters.Edx & CPUID_FEATURES_EDX_APIC) == 0) { /* APIC is not supported by the CPU */ return STATUS_EFI_UNSUPPORTED; } /* Get APIC base address */ *ApicBase = (PVOID)((UINT_PTR)XtLdrProtocol->Cpu.ReadModelSpecificRegister(0x1B) & 0xFFFFF000); /* Return success */ return STATUS_EFI_SUCCESS; } /** * Gets RSDP (ACPI 1.0) from EFI system configuration * * @param AcpiTable * Suplies a pointer to memory area where RSDP address will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Acpi::GetRsdpTable(OUT PVOID *AcpiTable) { EFI_GUID AcpiGuid = EFI_CONFIG_TABLE_ACPI_TABLE_GUID; EFI_STATUS Status; PVOID RsdpTable; /* Get RSDP (ACPI 1.0) table from system configuration tables */ Status = XtLdrProtocol->Utils.GetConfigurationTable(&AcpiGuid, &RsdpTable); if(Status != STATUS_EFI_SUCCESS || !ValidateAcpiTable(RsdpTable, 20)) { /* RSDP not found or checksum mismatch */ *AcpiTable = NULLPTR; return STATUS_EFI_NOT_FOUND; } /* RSDP found, return success */ *AcpiTable = RsdpTable; return STATUS_EFI_SUCCESS; } /** * Gets SMBIOS from EFI system configuration * * @param SmBiosTable * Suplies a pointer to memory area where SMBIOS address will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Acpi::GetSMBiosTable(OUT PVOID *SmBiosTable) { EFI_GUID SmBiosGuid = EFI_CONFIG_TABLE_SMBIOS_TABLE_GUID; PSMBIOS_TABLE_HEADER SmBios; EFI_STATUS Status; /* Get SMBIOS table from system configuration tables */ Status = XtLdrProtocol->Utils.GetConfigurationTable(&SmBiosGuid, (PVOID*)&SmBios); if(Status != STATUS_EFI_SUCCESS || !ValidateAcpiTable(SmBios, SmBios->Length)) { /* SMBIOS not found or checksum mismatch */ *SmBiosTable = NULLPTR; return STATUS_EFI_NOT_FOUND; } /* SMBIOS found, return success */ *SmBiosTable = SmBios; return STATUS_EFI_SUCCESS; } /** * Gets SMBIOS3 from EFI system configuration * * @param SmBiosTable * Suplies a pointer to memory area where SMBIOS3 address will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Acpi::GetSMBios3Table(OUT PVOID *SmBiosTable) { EFI_GUID SmBios3Guid = EFI_CONFIG_TABLE_SMBIOS3_TABLE_GUID; PSMBIOS3_TABLE_HEADER SmBios; EFI_STATUS Status; /* Get SMBIOS3 table from system configuration tables */ Status = XtLdrProtocol->Utils.GetConfigurationTable(&SmBios3Guid, (PVOID*)&SmBios); if(Status != STATUS_EFI_SUCCESS || !ValidateAcpiTable(SmBios, SmBios->Length)) { /* SMBIOS3 not found or checksum mismatch */ *SmBiosTable = NULLPTR; return STATUS_EFI_NOT_FOUND; } /* SMBIOS3 found, return success */ *SmBiosTable = SmBios; return STATUS_EFI_SUCCESS; } /** * Gets XSDP (ACPI 2.0) from EFI system configuration * * @param AcpiTable * Suplies a pointer to memory area where XSDP address will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Acpi::GetXsdpTable(OUT PVOID *AcpiTable) { EFI_GUID AcpiGuid = EFI_CONFIG_TABLE_ACPI20_TABLE_GUID; EFI_STATUS Status; PVOID XsdpTable; /* Get XSDP (ACPI 2.0) from system configuration tables */ Status = XtLdrProtocol->Utils.GetConfigurationTable(&AcpiGuid, &XsdpTable); if(Status != STATUS_EFI_SUCCESS || !ValidateAcpiTable(XsdpTable, 36)) { /* XSDP not found or checksum mismatch */ *AcpiTable = NULLPTR; return STATUS_EFI_NOT_FOUND; } /* XSDP found, return success */ *AcpiTable = XsdpTable; return STATUS_EFI_SUCCESS; } /** * Initializes ACPI module by opening XTLDR protocol and installing ACPI protocol. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Acpi::InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { EFI_GUID Guid = XT_ACPI_PROTOCOL_GUID; EFI_STATUS Status; /* Open the XTLDR protocol */ Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open the protocol, return error */ return STATUS_EFI_PROTOCOL_ERROR; } /* Set routines available via ACPI protocol */ AcpiProtocol.GetAcpiDescriptionPointer = GetAcpiDescriptionPointer; AcpiProtocol.GetAcpiTable = GetAcpiTable; AcpiProtocol.GetApicBase = GetApicBase; AcpiProtocol.GetRsdpTable = GetRsdpTable; AcpiProtocol.GetSMBiosTable = GetSMBiosTable; AcpiProtocol.GetSMBios3Table = GetSMBios3Table; AcpiProtocol.GetXsdpTable = GetXsdpTable; /* Install ACPI protocol */ return XtLdrProtocol->Protocol.Install(&AcpiProtocol, &Guid); } /** * Validates given ACPI table by calculating its checksum. * * @param Buffer * Supplies a pointer to the table to checksum. * * @param Size * Supplies the size of the table, in bytes. * * @return This routine returns TRUE if the table is valid, or FALSE otherwise. * * @since XT 1.0 */ XTCDECL BOOLEAN Acpi::ValidateAcpiTable(IN PVOID Buffer, IN UINT_PTR Size) { PUCHAR Pointer; UCHAR Sum; /* Initialize variables */ Sum = 0; Pointer = (PUCHAR)Buffer; /* Calculate checksum of given table */ while(Size != 0) { Sum = (UCHAR)(Sum + *Pointer); Pointer += 1; Size -= 1; } /* Return calculated checksum */ return (Sum == 0) ? TRUE : FALSE; } /** * This routine is the entry point of the XT EFI boot loader module. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS XtLdrModuleMain(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { /* Initialize ACPI module */ return Acpi::InitializeModule(ImageHandle, SystemTable); } ================================================ FILE: boot/xtldr/modules/acpi/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/acpi/data.cc * DESCRIPTION: ACPI module global and static data * DEVELOPERS: Rafal Kupiec */ #include /* ACPI Protocol */ XTBL_ACPI_PROTOCOL Acpi::AcpiProtocol; /* XTLDR protocol handler */ PXTBL_LOADER_PROTOCOL Acpi::XtLdrProtocol; ================================================ FILE: boot/xtldr/modules/acpi/includes/acpi.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/acpi/includes/acpi.hh * DESCRIPTION: XTLDR ACPI module header file * DEVELOPERS: Rafal Kupiec */ #ifndef __XTLDR_ACPI_ACPI_HH #define __XTLDR_ACPI_ACPI_HH #include /* ACPI module for XTLDR */ class Acpi { private: STATIC XTBL_ACPI_PROTOCOL AcpiProtocol; STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol; public: STATIC XTCDECL EFI_STATUS GetAcpiDescriptionPointer(OUT PVOID *AcpiTable); STATIC XTCDECL EFI_STATUS GetAcpiTable(IN CONST UINT Signature, IN PVOID PreviousTable, OUT PVOID *AcpiTable); STATIC XTCDECL EFI_STATUS GetApicBase(OUT PVOID *ApicBase); STATIC XTCDECL EFI_STATUS GetRsdpTable(OUT PVOID *AcpiTable); STATIC XTCDECL EFI_STATUS GetSMBiosTable(OUT PVOID *SmBiosTable); STATIC XTCDECL EFI_STATUS GetSMBios3Table(OUT PVOID *SmBiosTable); STATIC XTCDECL EFI_STATUS GetXsdpTable(OUT PVOID *AcpiTable); STATIC XTCDECL EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable); private: STATIC XTCDECL BOOLEAN ValidateAcpiTable(IN PVOID Buffer, IN UINT_PTR Size); }; #endif /* __XTLDR_ACPI_ACPI_HH */ ================================================ FILE: boot/xtldr/modules/beep/CMakeLists.txt ================================================ # XT Boot Loader Beep Module PROJECT(XTLDR_BEEP) # Specify include directories include_directories( ${EXECTOS_SOURCE_DIR}/sdk/xtdk ${XTLDR_BEEP_SOURCE_DIR}/includes) # Specify list of source code files list(APPEND XTLDR_BEEP_SOURCE ${XTLDR_BEEP_SOURCE_DIR}/beep.cc ${XTLDR_BEEP_SOURCE_DIR}/data.cc) # Link module executable add_executable(beep ${XTLDR_BEEP_SOURCE}) # Add linker libraries target_link_libraries(beep libxtldr libxtos) # Set proper binary name and install target set_target_properties(beep PROPERTIES SUFFIX .efi) set_install_target(beep efi/boot/xtldr/modules) # Set module entrypoint and subsystem set_entrypoint(beep "XtLdrModuleMain") set_linker_map(beep TRUE) set_subsystem(beep efi_boot_service_driver) ================================================ FILE: boot/xtldr/modules/beep/beep.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/beep/beep.cc * DESCRIPTION: XTLDR Beep Module * DEVELOPERS: Rafal Kupiec */ #include /* Beep module information */ MODULE_AUTHOR(L"Rafal Kupiec "); MODULE_DESCRIPTION(L"Plays a GRUB compatible tune via PC speaker"); MODULE_LICENSE(L"GPLv3"); MODULE_VERSION(L"0.1"); /** * Disables the PC speaker. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Beep::DisableToneBeep() { UCHAR Status; /* Stop the PC speaker */ Status = XtLdrProtocol->IoPort.Read8(0x61); XtLdrProtocol->IoPort.Write8(0x61, Status & 0xFC); } /** * Enables the PC speaker and plays a sound. * * @param Pitch * Specifies a pitch (in Hz) of the sound. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Beep::EnableToneBeep(IN UINT Pitch) { UINT Counter; UCHAR Status; /* Pitch only in range of 20..20000 */ if(Pitch < 20) { Pitch = 20; } else if(Pitch > 20000) { Pitch = 20000; } /* Set the desired frequency of the PIT clock */ Counter = 0x1234DD / Pitch; XtLdrProtocol->IoPort.Write8(0x43, 0xB6); XtLdrProtocol->IoPort.Write8(0x43, 0xB6); XtLdrProtocol->IoPort.Write8(0x42, (UCHAR) Counter & 0xFF); XtLdrProtocol->IoPort.Write8(0x42, (UCHAR) (Counter >> 8) & 0xFF); /* Start the PC speaker */ Status = XtLdrProtocol->IoPort.Read8(0x61); XtLdrProtocol->IoPort.Write8(0x61, Status | 0x03); } /** * Initializes BEEP module by opening XTLDR protocol and playing the tune. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Beep::InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { EFI_STATUS Status; PWCHAR Tune; /* Open the XTLDR protocol */ Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open the protocol, return error */ return STATUS_EFI_PROTOCOL_ERROR; } /* Play the tune set in the configuration */ XtLdrProtocol->Config.GetValue(L"TUNE", &Tune); PlayTune(Tune); /* Return success */ return STATUS_EFI_SUCCESS; } /** * This routine plays a tune. * * @param Arguments * Optional list of parameters provided with the command. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Beep::PlayTune(IN PWCHAR Arguments) { LONG Pitch, Duration, Tempo; PWCHAR Argument, LastArgument; /* Reset pitch and duration */ Duration = -1; Pitch = -1; Tempo = -1; /* Tokenize provided list of arguments */ Argument = XtLdrProtocol->WideString.Tokenize(Arguments, L" ", &LastArgument); /* Iterate over all arguments */ while(Argument != NULLPTR) { /* Check if tempo, pitch and duration are set */ if(Tempo < 0) { /* Set the tempo */ Tempo = WideStringToNumber(Argument); } else if(Pitch < 0) { /* Set the pitch */ Pitch = WideStringToNumber(Argument); } else { /* Set the duration */ Duration = WideStringToNumber(Argument); /* Check pitch value */ if(Pitch > 0) { /* Emit the beep tone */ EnableToneBeep(Pitch); } else { /* Stop emitting beep tone */ DisableToneBeep(); } /* Wait for duration time */ XtLdrProtocol->Utils.SleepExecution(60000 * Duration / Tempo); /* Reset pitch and duration */ Pitch = -1; Duration = -1; } /* Get next argument */ Argument = XtLdrProtocol->WideString.Tokenize(NULLPTR, L" ", &LastArgument); } /* Stop emitting beep tone */ DisableToneBeep(); } /** * Converts a wide string into a number. * * @param String * Supplies an input wide string. * * @return This routine returns the number that was converted from the wide string. * * @since XT 1.0 */ XTCDECL UINT Beep::WideStringToNumber(IN PWCHAR String) { ULONG Number = 0; /* Iterate over all characters until '\0' found */ do { /* Check if this is a digit */ if(*String - '0' < 10) { /* Add another digit to the number */ Number *= 10; Number += *String - '0'; } } while(*++String != L'\0'); /* Return number */ return Number; } /** * This routine is the entry point of the XT EFI boot loader module. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS XtLdrModuleMain(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { /* Initialize BEEP module */ return Beep::InitializeModule(ImageHandle, SystemTable); } ================================================ FILE: boot/xtldr/modules/beep/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/beep/data.cc * DESCRIPTION: BEEP module global and static data * DEVELOPERS: Rafal Kupiec */ #include /* XTLDR protocol handler */ PXTBL_LOADER_PROTOCOL Beep::XtLdrProtocol; ================================================ FILE: boot/xtldr/modules/beep/includes/beep.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/beep/includes/beep.hh * DESCRIPTION: XTLDR Beep Module header file * DEVELOPERS: Rafal Kupiec */ #ifndef __XTLDR_BEEP_BEEP_HH #define __XTLDR_BEEP_BEEP_HH #include /* BEEP module for XTLDR */ class Beep { private: STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol; public: STATIC XTCDECL EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable); STATIC XTCDECL VOID PlayTune(IN PWCHAR Arguments); private: STATIC XTCDECL VOID DisableToneBeep(); STATIC XTCDECL VOID EnableToneBeep(IN UINT Pitch); STATIC XTCDECL UINT WideStringToNumber(IN PWCHAR String); }; #endif /* __XTLDR_BEEP_BEEP_HH */ ================================================ FILE: boot/xtldr/modules/chainldr/CMakeLists.txt ================================================ # XTLDR Chain Loader Module PROJECT(XTLDR_CHAINLDR) # Specify include directories include_directories( ${EXECTOS_SOURCE_DIR}/sdk/xtdk ${XTLDR_CHAINLDR_SOURCE_DIR}/includes) # Specify list of source code files list(APPEND XTLDR_CHAINLDR_SOURCE ${XTLDR_CHAINLDR_SOURCE_DIR}/chainldr.cc ${XTLDR_CHAINLDR_SOURCE_DIR}/data.cc) # Link module executable add_executable(chainldr ${XTLDR_CHAINLDR_SOURCE}) # Add linker libraries target_link_libraries(chainldr libxtldr libxtos) # Set proper binary name and install target set_target_properties(chainldr PROPERTIES SUFFIX .efi) set_install_target(chainldr efi/boot/xtldr/modules) # Set module entrypoint and subsystem set_entrypoint(chainldr "XtLdrModuleMain") set_linker_map(chainldr TRUE) set_subsystem(chainldr efi_boot_service_driver) ================================================ FILE: boot/xtldr/modules/chainldr/chainldr.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/chainldr/chainldr.cc * DESCRIPTION: XTLDR Chain Loader * DEVELOPERS: Rafal Kupiec */ #include /* ChainLoader module information */ MODULE_AUTHOR(L"Rafal Kupiec "); MODULE_DESCRIPTION(L"XTLDR Chain Loader"); MODULE_LICENSE(L"GPLv3"); MODULE_VERSION(L"0.1"); /** * Chainloads another boot loader. * * @param Parameters * Input parameters with detailed system configuration. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS ChainLoader::BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters) { EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; EFI_MEMMAP_DEVICE_PATH MemoryDevicePath[2]; PEFI_LOADED_IMAGE_PROTOCOL LoadedImage; EFI_HANDLE DiskHandle, LoaderHandle; PEFI_FILE_HANDLE FsHandle, BootDir; EFI_STATUS Status; SIZE_T LoaderSize; PVOID LoaderData; /* Check if image file is provided */ if(Parameters->KernelFile == NULLPTR) { /* No image filename provided, return error code */ XtLdrProtocol->Debug.Print(L"ERROR: No EFI image filename provided\n"); return STATUS_EFI_INVALID_PARAMETER; } /* Open EFI volume */ Status = XtLdrProtocol->Disk.OpenVolume(Parameters->DevicePath, &DiskHandle, &FsHandle); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open a volume, return error code */ XtLdrProtocol->Debug.Print(L"ERROR: Unable to open boot volume (Status Code: 0x%zX)\n", Status); return Status; } /* Open boot directory and close FS handle */ Status = FsHandle->Open(FsHandle, &BootDir, Parameters->EfiPath, EFI_FILE_MODE_READ, 0); FsHandle->Close(FsHandle); /* Check if system path directory opened successfully */ if(Status != STATUS_EFI_SUCCESS) { /* Failed to open directory */ XtLdrProtocol->Debug.Print(L"ERROR: Unable to open system boot directory (Status Code: 0x%zX)\n", Status); /* Close volume and return error code */ XtLdrProtocol->Disk.CloseVolume(&DiskHandle); return Status; } /* Read EFI image file from disk and close both directory and EFI volume */ Status = XtLdrProtocol->Disk.ReadFile(BootDir, Parameters->KernelFile, &LoaderData, &LoaderSize); BootDir->Close(BootDir); XtLdrProtocol->Disk.CloseVolume(&DiskHandle); /* Setup device path for EFI image */ MemoryDevicePath[0].Header.Length[0] = sizeof(EFI_MEMMAP_DEVICE_PATH); MemoryDevicePath[0].Header.Length[1] = sizeof(EFI_MEMMAP_DEVICE_PATH) >> 8; MemoryDevicePath[0].Header.Type = EFI_HARDWARE_DEVICE_PATH; MemoryDevicePath[0].Header.SubType = EFI_HARDWARE_MEMMAP_DP; MemoryDevicePath[0].MemoryType = EfiLoaderData; MemoryDevicePath[0].StartingAddress = (UINT_PTR)LoaderData; MemoryDevicePath[0].EndingAddress = (UINT_PTR)LoaderData + LoaderSize; MemoryDevicePath[1].Header.Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL); MemoryDevicePath[1].Header.Length[1] = sizeof(EFI_DEVICE_PATH_PROTOCOL) >> 8; MemoryDevicePath[1].Header.Type = EFI_END_DEVICE_PATH; MemoryDevicePath[1].Header.SubType = EFI_END_ENTIRE_DP; /* Load EFI image */ Status = XtLdrProtocol->Utils.LoadEfiImage((PEFI_DEVICE_PATH_PROTOCOL)MemoryDevicePath, LoaderData, LoaderSize, &LoaderHandle); if(Status != STATUS_EFI_SUCCESS) { /* Failed to chainload EFI binary, return error code */ XtLdrProtocol->Debug.Print(L"ERROR: Unable to chainload '%S' (Status Code: 0x%zX)\n", Parameters->KernelFile, Status); return Status; } /* Access loaded image protocol */ Status = XtLdrProtocol->Protocol.OpenHandle(LoaderHandle, (PVOID *)&LoadedImage, &LIPGuid); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open EFI_LOADED_IMAGE_PROTOCOL, return error code */ XtLdrProtocol->Debug.Print(L"ERROR: Unable to access binary interface (Status Code: 0x%zX)\n", Status); return Status; } /* Check if parameters provided */ if(Parameters->Parameters) { /* Pass arguments to chainloaded image */ LoadedImage->LoadOptionsSize = XtLdrProtocol->WideString.Length(Parameters->Parameters, 0) * sizeof(WCHAR); LoadedImage->LoadOptions = Parameters->Parameters; } /* Set device handle as LoadImage() is not going to do it */ LoadedImage->DeviceHandle = DiskHandle; /* Chainload EFI image */ return XtLdrProtocol->Utils.StartEfiImage(LoaderHandle); } /** * Initializes CHAINLDR module by opening XTLDR protocol and installing CHAINLOADER protocol. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS ChainLoader::InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { EFI_GUID Guid = XT_CHAIN_BOOT_PROTOCOL_GUID; EFI_STATUS Status; /* Open the XTLDR protocol */ Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open the protocol, return error */ return STATUS_EFI_PROTOCOL_ERROR; } /* Set routines available via ChainLoader boot protocol */ BootProtocol.BootSystem = BootSystem; /* Register XTOS boot protocol */ XtLdrProtocol->Boot.RegisterProtocol(L"CHAINLOADER", &Guid); /* Install XTOS protocol */ return XtLdrProtocol->Protocol.Install(&BootProtocol, &Guid); } /** * This routine is the entry point of the XT EFI boot loader module. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS XtLdrModuleMain(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { /* Initialize CHAINLDR module */ return ChainLoader::InitializeModule(ImageHandle, SystemTable); } ================================================ FILE: boot/xtldr/modules/chainldr/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/chainldr/data.cc * DESCRIPTION: CHAINLDR module global and static data * DEVELOPERS: Rafal Kupiec */ #include /* ChainLoader Boot Protocol */ XTBL_BOOT_PROTOCOL ChainLoader::BootProtocol; /* XTLDR protocol handler */ PXTBL_LOADER_PROTOCOL ChainLoader::XtLdrProtocol; ================================================ FILE: boot/xtldr/modules/chainldr/includes/chainldr.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/chainldr/includes/chainldr.hh * DESCRIPTION: XTLDR Chain Loader header file * DEVELOPERS: Rafal Kupiec */ #ifndef __XTLDR_CHAINLDR_CHAINLDR_HH #define __XTLDR_CHAINLDR_CHAINLDR_HH #include /* CHAINLDR module for XTLDR */ class ChainLoader { private: STATIC XTBL_BOOT_PROTOCOL BootProtocol; STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol; public: STATIC XTCDECL EFI_STATUS BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters); STATIC XTCDECL EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable); }; #endif /* __XTLDR_CHAINLDR_CHAINLDR_HH */ ================================================ FILE: boot/xtldr/modules/dummy/CMakeLists.txt ================================================ # XT Boot Loader Dummy Module PROJECT(XTLDR_DUMMY) # Specify include directories include_directories( ${EXECTOS_SOURCE_DIR}/sdk/xtdk ${XTLDR_DUMMY_SOURCE_DIR}/includes) # Specify list of source code files list(APPEND XTLDR_DUMMY_SOURCE ${XTLDR_DUMMY_SOURCE_DIR}/dummy.cc ${XTLDR_DUMMY_SOURCE_DIR}/data.cc) # Link module executable add_executable(dummy ${XTLDR_DUMMY_SOURCE}) # Add linker libraries target_link_libraries(dummy libxtldr) # Set proper binary name and install target set_target_properties(dummy PROPERTIES SUFFIX .efi) set_install_target(dummy efi/boot/xtldr/modules) # Set module entrypoint and subsystem set_entrypoint(dummy "XtLdrModuleMain") set_linker_map(dummy TRUE) set_subsystem(dummy efi_boot_service_driver) ================================================ FILE: boot/xtldr/modules/dummy/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/dummy/data.cc * DESCRIPTION: Dummy XTLDR module global and static data * DEVELOPERS: Rafal Kupiec */ #include /* Dummy Boot Protocol handler */ XTBL_BOOT_PROTOCOL Dummy::DummyProtocol; /* XTLDR protocol handler */ PXTBL_LOADER_PROTOCOL Dummy::XtLdrProtocol; ================================================ FILE: boot/xtldr/modules/dummy/dummy.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/dummy/dummy.cc * DESCRIPTION: XTLDR Dummy Module * DEVELOPERS: Rafal Kupiec */ #include /* Dummy module information */ MODULE_AUTHOR(L"Rafal Kupiec "); MODULE_DESCRIPTION(L"XTLDR Dummy Module"); MODULE_LICENSE(L"GPLv3"); MODULE_VERSION(L"0.1"); /** * Stub boot routine. * * @param Parameters * Supplies all parameters associated with the chosen boot menu entry. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Dummy::BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters) { return STATUS_EFI_SUCCESS; } /** * Initializes DUMMY module by opening XTLDR protocol and installing DUMMY protocol. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Dummy::InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { EFI_GUID DummyGuid = XT_DUMMY_BOOT_PROTOCOL_GUID; EFI_STATUS Status; /* Open the XTLDR protocol */ Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open the protocol, return error */ return STATUS_EFI_PROTOCOL_ERROR; } /* Set boot protocol routines */ DummyProtocol.BootSystem = BootSystem; /* Register XTOS boot protocol */ XtLdrProtocol->Boot.RegisterProtocol(L"DUMMYOS", &DummyGuid); /* Register DUMMY protocol as XTOS boot protocol */ return XtLdrProtocol->Protocol.Install(&DummyProtocol, &DummyGuid); } /** * This routine is the entry point of the XT EFI boot loader module. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS XtLdrModuleMain(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { /* Initialize DUMMY module */ return Dummy::InitializeModule(ImageHandle, SystemTable); } ================================================ FILE: boot/xtldr/modules/dummy/includes/dummy.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/dummy/includes/dummy.hh * DESCRIPTION: XTLDR Dummy Module header file * DEVELOPERS: Rafal Kupiec */ #ifndef __XTLDR_DUMMY_DUMMY_HH #define __XTLDR_DUMMY_DUMMY_HH #include /* DUMMY module for XTLDR */ class Dummy { private: STATIC XTBL_BOOT_PROTOCOL DummyProtocol; STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol; public: STATIC EFI_STATUS BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters); STATIC EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable); }; #endif/* __XTLDR_DUMMY_DUMMY_HH */ ================================================ FILE: boot/xtldr/modules/framebuf/CMakeLists.txt ================================================ # XTLDR FrameBuffer support module PROJECT(XTLDR_FRAMEBUF) # Specify include directories include_directories( ${EXECTOS_SOURCE_DIR}/sdk/xtdk ${XTLDR_FRAMEBUF_SOURCE_DIR}/includes) # Specify list of source code files list(APPEND XTLDR_FRAMEBUF_SOURCE ${XTLDR_FRAMEBUF_SOURCE_DIR}/framebuf.cc ${XTLDR_FRAMEBUF_SOURCE_DIR}/data.cc) # Link bootloader executable add_executable(framebuf ${XTLDR_FRAMEBUF_SOURCE}) # Add linker libraries target_link_libraries(framebuf libxtldr) # Set proper binary name and install target set_target_properties(framebuf PROPERTIES SUFFIX .efi) set_install_target(framebuf efi/boot/xtldr/modules) # Set module entrypoint and subsystem set_entrypoint(framebuf "XtLdrModuleMain") set_linker_map(framebuf TRUE) set_subsystem(framebuf efi_boot_service_driver) ================================================ FILE: boot/xtldr/modules/framebuf/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/framebuf/data.cc * DESCRIPTION: EFI framebuffer module global and static data * DEVELOPERS: Rafal Kupiec */ #include /* Framebuffer display information */ XTBL_FRAMEBUFFER_INFORMATION FrameBuffer::DisplayInfo; /* Framebuffer protocol handler */ XTBL_FRAMEBUFFER_PROTOCOL FrameBuffer::FbProtocol; /* XTLDR protocol handler */ PXTBL_LOADER_PROTOCOL FrameBuffer::XtLdrProtocol; ================================================ FILE: boot/xtldr/modules/framebuf/framebuf.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/framebuf/framebuf.cc * DESCRIPTION: EFI framebuffer support module for XTLDR * DEVELOPERS: Rafal Kupiec */ #include /* PE/COFF_O module information */ MODULE_AUTHOR(L"Rafal Kupiec "); MODULE_DESCRIPTION(L"EFI FB (FrameBuffer) support"); MODULE_LICENSE(L"GPLv3"); MODULE_VERSION(L"0.2"); /** * Finds a PCI Display Adapter and returns its framebuffer address. * * @param Address * Supplies a pointer to the memory area where framebuffer address will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS FrameBuffer::FindFramebufferAddress(OUT PEFI_PHYSICAL_ADDRESS Address) { EFI_GUID PciIoGuid = EFI_PCI_IO_PROTOCOL_GUID; PEFI_ACPI_ADDRESS_SPACE_DESCRIPTOR BarInfo; PEFI_PCI_IO_PROTOCOL IoProtocol; ULONGLONG FramebufAddressLength; PCI_TYPE0_DEVICE PciDevice; PVOID FramebufAddress; UINT_PTR HandlesCount; EFI_HANDLE *Handles; EFI_STATUS Status; UINT Index; /* Initialize variables */ FramebufAddressLength = 0; Handles = NULLPTR; /* Locate EFI_PCI_IO_PROTOCOL handles */ Status = XtLdrProtocol->Protocol.LocateHandles(&Handles, &HandlesCount, &PciIoGuid); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get handles, return error code */ XtLdrProtocol->Debug.Print(L"ERROR: Failed to get handles (Status Code: 0x%zX)\n", Status); return Status; } /* Iterate through handles */ for(Index = 0; Index < HandlesCount; Index++) { /* Open EFI_PCI_IO_PROTOCOL handle */ Status = XtLdrProtocol->Protocol.OpenHandle(Handles[Index], (PVOID *)&IoProtocol, &PciIoGuid); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open protocol, continue with next handle */ XtLdrProtocol->Debug.Print(L"ERROR: Failed to open protocol (Status Code: 0x%zX)\n", Status); continue; } /* Read PCI controller registers from PCI configuration space */ Status = IoProtocol->Pci.Read(IoProtocol, EfiPciIoWidthUint32, 0, sizeof(PciDevice) / sizeof(UINT), &PciDevice); if(Status != STATUS_EFI_SUCCESS) { /* Failed to read PCI device class */ XtLdrProtocol->Debug.Print(L"ERROR: Failed to read class (Status Code: 0x%zX)\n", Status); /* Close protocol and continue with next handle */ XtLdrProtocol->Protocol.Close(&Handles[Index], &PciIoGuid); continue; } /* Check if device is a graphics adapter */ if(PciDevice.Hdr.ClassCode[2] != 0x03) { /* Not a graphics adapter, close protocol and continue with next handle */ XtLdrProtocol->Protocol.Close(&Handles[Index], &PciIoGuid); continue; } /* Iterate through all PCI device's Base Address Registers (BARs) */ for(UINT Bars = 0; Bars < 6; Bars++) { /* Get BAR attributes */ Status = IoProtocol->GetBarAttributes(IoProtocol, Bars, NULLPTR, (VOID **)&BarInfo); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get BAR attributes, continue with next BAR */ continue; } /* Check if this BAR is 'Memory Range' of 'ACPI QWORD Address Space' */ if(BarInfo->SpaceDescriptor == EFI_ACPI_ADDRESS64_SPACE_DESCRIPTOR && BarInfo->ResourceType == EFI_ACPI_ADDRESS_SPACE_TYPE_MEMORY) { /* Check if this BAR is the biggest we've seen so far */ if(BarInfo->AddressLength > FramebufAddressLength) { /* The biggest BAR should be the framebuffer; save its address and length */ FramebufAddress = (PVOID)(ULONG_PTR)(BarInfo->AddressRangeMin << 16); FramebufAddressLength = BarInfo->AddressLength; } } } /* Close handle and continue with next one */ XtLdrProtocol->Protocol.Close(&Handles[Index], &PciIoGuid); } /* Set framebuffer address and return success */ *Address = (EFI_PHYSICAL_ADDRESS)FramebufAddress; return STATUS_EFI_SUCCESS; } /** * Calculates color mask and shift based upon pixel bit mask. * * @param PixelBitMask * Provides a pixel bit mask. * * @param ColorSize * Supplies a pointer to the memory area where the color size will be stored. * * @param ColorShift * Supplies a pointer to the memory area where the color shift (position) will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID FrameBuffer::GetColorMask(IN UINT PixelBitMask, OUT PUSHORT ColorSize, OUT PUSHORT ColorShift) { UINT Shift, Size; /* Initialize variables */ Shift = 0; Size = 0; /* Make sure EfiMask is not zero */ if(PixelBitMask) { /* Get color shift */ while((PixelBitMask & 1) == 0) { Shift++; PixelBitMask >>= 1; } /* Get color size */ while((PixelBitMask & 1) == 1) { Size++; PixelBitMask >>= 1; } } /* Set color mask and shift */ *ColorShift = Shift; *ColorSize = Size; } /** * Provides an EFI Frame Buffer protocol driver name used for initialization. * * @param Protocol * Supplies a pointer to the memory area where framebuffer driver information will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS FrameBuffer::GetDisplayDriver(OUT PEFI_GRAPHICS_PROTOCOL Protocol) { /* Check if framebuffer is initialized */ if(!DisplayInfo.Initialized) { /* Return error if framebuffer is not initialized */ return STATUS_EFI_NOT_READY; } /* Copy framebuffer driver information */ *Protocol = DisplayInfo.Protocol; /* Return success */ return STATUS_EFI_SUCCESS; } /** * Returns information about EFI Frame Buffer. * * @param FbInfo * Supplies a pointer to the memory area where framebuffer information will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS FrameBuffer::GetDisplayInformation(OUT PEFI_PHYSICAL_ADDRESS FrameBufferBase, OUT PULONG_PTR FrameBufferSize, OUT PXTBL_FRAMEBUFFER_MODE_INFORMATION ModeInfo) { /* Check if framebuffer is initialized */ if(!DisplayInfo.Initialized) { /* Return error if framebuffer is not initialized */ return STATUS_EFI_NOT_READY; } /* Set basic framebuffer information */ *FrameBufferBase = DisplayInfo.FrameBufferBase; *FrameBufferSize = DisplayInfo.FrameBufferSize; /* Set framebuffer mode information */ ModeInfo->Width = DisplayInfo.ModeInfo.Width; ModeInfo->Height = DisplayInfo.ModeInfo.Height; ModeInfo->Depth = DisplayInfo.ModeInfo.Depth; ModeInfo->RefreshRate = DisplayInfo.ModeInfo.RefreshRate; ModeInfo->BitsPerPixel = DisplayInfo.ModeInfo.BitsPerPixel; ModeInfo->BytesPerPixel = DisplayInfo.ModeInfo.BytesPerPixel; ModeInfo->PixelsPerScanLine = DisplayInfo.ModeInfo.PixelsPerScanLine; ModeInfo->Pitch = DisplayInfo.ModeInfo.Pitch; ModeInfo->PixelFormat = DisplayInfo.ModeInfo.PixelFormat; ModeInfo->PixelInformation = DisplayInfo.ModeInfo.PixelInformation; /* Return success */ return STATUS_EFI_SUCCESS; } /** * Gets information about the current display mode and stores it in internal structure. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS FrameBuffer::GetModeInformation() { PEFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInfo; EFI_PIXEL_BITMASK PixelBitMask; XTSTATUS Status; UINT_PTR Size; switch(DisplayInfo.Protocol) { case GOP: /* Query GOP mode information */ Status = DisplayInfo.Driver.Gop->QueryMode(DisplayInfo.Driver.Gop, DisplayInfo.Driver.Gop->Mode->Mode, &Size, &ModeInfo); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get GOP mode information, return error */ return Status; } /* Get pixel bit mask information */ GetPixelInformation(&DisplayInfo.Driver.Gop->Mode->Info->PixelInformation); /* Store GOP framebuffer information */ DisplayInfo.ModeInfo.Width = DisplayInfo.Driver.Gop->Mode->Info->HorizontalResolution; DisplayInfo.ModeInfo.Height = DisplayInfo.Driver.Gop->Mode->Info->VerticalResolution; DisplayInfo.ModeInfo.Depth = DisplayInfo.ModeInfo.BitsPerPixel; DisplayInfo.ModeInfo.PixelsPerScanLine = DisplayInfo.Driver.Gop->Mode->Info->PixelsPerScanLine; DisplayInfo.ModeInfo.Pitch = DisplayInfo.ModeInfo.PixelsPerScanLine * (DisplayInfo.ModeInfo.BitsPerPixel / 8); DisplayInfo.ModeInfo.RefreshRate = 0; /* Store pixel format information and frame buffer size */ DisplayInfo.ModeInfo.PixelFormat = DisplayInfo.Driver.Gop->Mode->Info->PixelFormat; DisplayInfo.FrameBufferSize = DisplayInfo.Driver.Gop->Mode->FrameBufferSize; break; case UGA: /* Query UGA mode information */ Status = DisplayInfo.Driver.Uga->GetMode(DisplayInfo.Driver.Uga, &DisplayInfo.ModeInfo.Width, &DisplayInfo.ModeInfo.Height, &DisplayInfo.ModeInfo.Depth, &DisplayInfo.ModeInfo.RefreshRate); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get UGA mode information, return error */ return Status; } /* Get pixel bit mask information */ PixelBitMask = (EFI_PIXEL_BITMASK){0, 0, 0, 0}; GetPixelInformation(&PixelBitMask); /* Store UGA framebuffer information */ DisplayInfo.ModeInfo.PixelsPerScanLine = DisplayInfo.ModeInfo.Width; DisplayInfo.ModeInfo.Pitch = DisplayInfo.ModeInfo.PixelsPerScanLine * (DisplayInfo.ModeInfo.BitsPerPixel / 8); /* Store pixel format information and recalculate frame buffer size */ DisplayInfo.ModeInfo.PixelFormat = PixelBlueGreenRedReserved8BitPerColor; DisplayInfo.FrameBufferSize = DisplayInfo.ModeInfo.Width * DisplayInfo.ModeInfo.Height * DisplayInfo.ModeInfo.BytesPerPixel + 1024; break; default: /* This should never be reached as no other display driver is supported */ break; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Gets pixel information based on the reported pixel format. * * @param FrameBufferInfo * Supplies a pointer to the framebuffer information structure. * * @param PixelsBitMask * Supplies a pointer to the pixel bit mask information provided by EFI graphics protocol. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID FrameBuffer::GetPixelInformation(IN PEFI_PIXEL_BITMASK PixelsBitMask) { UINT CompoundMask; /* Check reported pixel format */ switch(DisplayInfo.ModeInfo.PixelFormat) { case PixelBlueGreenRedReserved8BitPerColor: /* BGRR, 32 bits per pixel */ DisplayInfo.ModeInfo.BitsPerPixel = 32; DisplayInfo.ModeInfo.PixelInformation.BlueShift = 0; DisplayInfo.ModeInfo.PixelInformation.BlueSize = 8; DisplayInfo.ModeInfo.PixelInformation.GreenShift = 8; DisplayInfo.ModeInfo.PixelInformation.GreenSize = 8; DisplayInfo.ModeInfo.PixelInformation.RedShift = 16; DisplayInfo.ModeInfo.PixelInformation.RedSize = 8; DisplayInfo.ModeInfo.PixelInformation.ReservedShift = 24; DisplayInfo.ModeInfo.PixelInformation.ReservedSize = 8; break; case PixelRedGreenBlueReserved8BitPerColor: /* RGBR, 32 bits per pixel */ DisplayInfo.ModeInfo.BitsPerPixel = 32; DisplayInfo.ModeInfo.PixelInformation.BlueShift = 16; DisplayInfo.ModeInfo.PixelInformation.BlueSize = 8; DisplayInfo.ModeInfo.PixelInformation.GreenShift = 8; DisplayInfo.ModeInfo.PixelInformation.GreenSize = 8; DisplayInfo.ModeInfo.PixelInformation.RedShift = 0; DisplayInfo.ModeInfo.PixelInformation.RedSize = 8; DisplayInfo.ModeInfo.PixelInformation.ReservedShift = 24; DisplayInfo.ModeInfo.PixelInformation.ReservedSize = 8; break; case PixelBitMask: /* Assume 32 bits per pixel */ DisplayInfo.ModeInfo.BitsPerPixel = 32; /* Calculate compound mask */ CompoundMask = PixelsBitMask->RedMask | PixelsBitMask->GreenMask | PixelsBitMask->BlueMask | PixelsBitMask->ReservedMask; /* Recalculate bits per pixel */ while((CompoundMask & (1 << 31)) == 0) { DisplayInfo.ModeInfo.BitsPerPixel--; CompoundMask <<= 1; } /* Set pixel information */ GetColorMask(PixelsBitMask->RedMask, &DisplayInfo.ModeInfo.PixelInformation.RedSize, &DisplayInfo.ModeInfo.PixelInformation.RedShift); GetColorMask(PixelsBitMask->GreenMask, &DisplayInfo.ModeInfo.PixelInformation.GreenSize, &DisplayInfo.ModeInfo.PixelInformation.GreenShift); GetColorMask(PixelsBitMask->BlueMask, &DisplayInfo.ModeInfo.PixelInformation.BlueSize, &DisplayInfo.ModeInfo.PixelInformation.BlueShift); GetColorMask(PixelsBitMask->ReservedMask, &DisplayInfo.ModeInfo.PixelInformation.ReservedSize, &DisplayInfo.ModeInfo.PixelInformation.ReservedShift); break; default: /* Unknown pixel format */ DisplayInfo.ModeInfo.BitsPerPixel = 0; DisplayInfo.ModeInfo.PixelInformation.BlueShift = 0; DisplayInfo.ModeInfo.PixelInformation.BlueSize = 0; DisplayInfo.ModeInfo.PixelInformation.GreenShift = 0; DisplayInfo.ModeInfo.PixelInformation.GreenSize = 0; DisplayInfo.ModeInfo.PixelInformation.RedShift = 0; DisplayInfo.ModeInfo.PixelInformation.RedSize = 0; DisplayInfo.ModeInfo.PixelInformation.ReservedShift = 0; DisplayInfo.ModeInfo.PixelInformation.ReservedSize = 0; break; } /* Calculate bytes per pixel based on bits per pixel */ DisplayInfo.ModeInfo.BytesPerPixel = DisplayInfo.ModeInfo.BitsPerPixel >> 3; } /** * Determines the preferred (native) screen resolution from EDID. This works only with GOP. * * @param PreferredWidth * Supplies a pointer to the memory area where preferred screen width will be stored. * * @param PreferredHeight * Supplies a pointer to the memory area where preferred screen height will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS FrameBuffer::GetPreferredScreenResolution(OUT PUINT PreferredWidth, OUT PUINT PreferredHeight) { EFI_GUID GopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; EFI_GUID EdidGuid = EFI_EDID_ACTIVE_PROTOCOL_GUID; PEFI_EDID_ACTIVE_PROTOCOL ActiveEdid; EFI_STATUS Status; /* Check if framebuffer is initialized */ if(!DisplayInfo.Initialized) { /* Framebuffer not ready to use EDID protocol */ return STATUS_EFI_NOT_READY; } /* Check if GOP device driver is used */ if(DisplayInfo.Protocol != GOP) { /* Unsupported device driver */ return STATUS_EFI_UNSUPPORTED; } /* Open EDID protocol */ Status = XtLdrProtocol->Protocol.OpenHandle(DisplayInfo.Handle, (PVOID *)&ActiveEdid, &EdidGuid); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open EDID protocol, close GOP protocol and return */ XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &GopGuid); return Status; } /* Return preferred screen resolution */ *PreferredWidth = ActiveEdid->Edid[0x38] | ((ActiveEdid->Edid[0x3A] & 0xF0) << 4); *PreferredHeight = ActiveEdid->Edid[0x3B] | ((ActiveEdid->Edid[0x3D] & 0xF0) << 4); /* Close EDID & GOP protocols */ XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &EdidGuid); /* Return success */ return STATUS_EFI_SUCCESS; } /** * Initializes FrameBuffer device on GOP and UGA compatible adapters. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS FrameBuffer::InitializeDisplay() { EFI_GUID GopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; EFI_GUID UgaGuid = EFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL_GUID; PEFI_GRAPHICS_OUTPUT_MODE_INFORMATION GopModeInfo; UINT Depth, QueryMode, Refresh; UINT_PTR InfoSize; EFI_STATUS Status; /* Check if framebuffer already initialized */ if(!DisplayInfo.Initialized) { /* Print debug message */ XtLdrProtocol->Debug.Print(L"Initializing framebuffer device\n"); /* Attempt to open EFI GOP protocol */ Status = XtLdrProtocol->Protocol.Open(&DisplayInfo.Handle, (PVOID*)&DisplayInfo.Driver.Gop, &GopGuid); /* Check if Graphics Output Protocol (GOP) is available */ if(Status == STATUS_EFI_SUCCESS) { /* Check if there are any video modes available */ if(DisplayInfo.Driver.Gop->Mode->MaxMode == 0) { /* No video modes available */ XtLdrProtocol->Debug.Print(L"ERROR: No GOP video mode available\n"); /* Close GOP protocol and return error */ XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &GopGuid); return STATUS_EFI_UNSUPPORTED; } /* Query current graphics mode */ QueryMode = DisplayInfo.Driver.Gop->Mode == NULLPTR ? 0 : DisplayInfo.Driver.Gop->Mode->Mode; Status = DisplayInfo.Driver.Gop->QueryMode(DisplayInfo.Driver.Gop, QueryMode, &InfoSize, &GopModeInfo); if(Status == STATUS_EFI_NOT_STARTED) { /* Set the mode to circumvent buggy UEFI firmware */ Status = DisplayInfo.Driver.Gop->SetMode(DisplayInfo.Driver.Gop, 0); } if(Status != STATUS_EFI_SUCCESS) { /* Unable to query GOP modes */ XtLdrProtocol->Debug.Print(L"ERROR: Failed to get GOP native mode (Status Code: 0x%zX)\n"); /* Close GOP protocol and return error */ XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &GopGuid); return STATUS_EFI_UNSUPPORTED; } /* Store frame buffer base address and protocol used */ DisplayInfo.FrameBufferBase = DisplayInfo.Driver.Gop->Mode->FrameBufferBase; DisplayInfo.DefaultMode = DisplayInfo.Driver.Gop->Mode->Mode; DisplayInfo.Protocol = GOP; /* Get current mode information */ Status = GetModeInformation(); if(Status != STATUS_EFI_SUCCESS) { /* Unable to get mode information */ XtLdrProtocol->Debug.Print(L"ERROR: Failed to get GOP mode information (Status Code: 0x%zX)\n"); /* Close GOP protocol and return error */ XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &GopGuid); return STATUS_EFI_UNSUPPORTED; } /* Found GOP */ XtLdrProtocol->Debug.Print(L"Found EFI-GOP compatible display adapter @ %P (%zu bytes)\n", DisplayInfo.FrameBufferBase, DisplayInfo.FrameBufferSize); /* Close GOP protocol */ Status = XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &GopGuid); } else { /* GOP is unavailable, attempt to open UGA protocol */ Status = XtLdrProtocol->Protocol.Open(&DisplayInfo.Handle, (PVOID*)&DisplayInfo.Driver.Uga, &UgaGuid); /* Check if Universal Graphics Adapter (UGA) is available */ if(Status == STATUS_EFI_SUCCESS) { /* Get current video mode */ Status = DisplayInfo.Driver.Uga->GetMode(DisplayInfo.Driver.Uga, &DisplayInfo.ModeInfo.Width, &DisplayInfo.ModeInfo.Height, &Depth, &Refresh); if(Status != STATUS_EFI_SUCCESS) { /* Unable to get current UGA mode */ XtLdrProtocol->Debug.Print(L"ERROR: Failed to get current UGA mode (Status Code: 0x%zX)\n", Status); /* Close UGA protocol and return error */ XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &UgaGuid); return STATUS_EFI_DEVICE_ERROR; } /* Find framebuffer address */ Status = FindFramebufferAddress(&DisplayInfo.FrameBufferBase); if(Status != STATUS_EFI_SUCCESS) { /* Unable to find framebuffer address */ XtLdrProtocol->Debug.Print(L"ERROR: Failed to get EFI FB address (Status Code: 0x%zX)\n", Status); /* Close UGA protocol and return error */ XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &UgaGuid); return STATUS_EFI_DEVICE_ERROR; } /* Store framebuffer protocol information */ DisplayInfo.DefaultMode = 0; DisplayInfo.Protocol = UGA; /* Get mode information */ Status = GetModeInformation(); if(Status != STATUS_EFI_SUCCESS) { /* Unable to get mode information */ XtLdrProtocol->Debug.Print(L"ERROR: Failed to get UGA mode information (Status Code: 0x%zX)\n"); return STATUS_EFI_UNSUPPORTED; } /* Found UGA */ XtLdrProtocol->Debug.Print(L"Found EFI-UGA compatible display adapter @ %P (%zu bytes)\n", DisplayInfo.FrameBufferBase, DisplayInfo.FrameBufferSize); /* Close UGA protocol */ XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &UgaGuid); } } /* Make sure framebuffer initialized properly */ if(DisplayInfo.Protocol == NONE) { /* GOP and UGA unavailable */ XtLdrProtocol->Debug.Print(L"WARNING: No display adapter found!\n"); return STATUS_EFI_NOT_FOUND; } XtLdrProtocol->Debug.Print(L"Current screen resolution is %ux%ux%u\n", DisplayInfo.ModeInfo.Width, DisplayInfo.ModeInfo.Height, DisplayInfo.ModeInfo.BitsPerPixel); /* Set framebuffer initialization flag */ DisplayInfo.Initialized = TRUE; } /* Return success */ return STATUS_SUCCESS; } /** * Initializes FRAMEBUF module by opening XTLDR protocol and installing FRAMEBUF protocol. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS FrameBuffer::InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { EFI_GUID Guid = XT_FRAMEBUFFER_PROTOCOL_GUID; EFI_STATUS Status; /* Open the XTLDR protocol */ Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open loader protocol */ return STATUS_EFI_PROTOCOL_ERROR; } /* Set initial framebuffer state */ DisplayInfo.Protocol = NONE; DisplayInfo.Initialized = FALSE; /* Set routines available via XTLDR framebuffer protocol */ FbProtocol.GetDisplayDriver = GetDisplayDriver; FbProtocol.GetDisplayInformation = GetDisplayInformation; FbProtocol.GetPreferredScreenResolution = GetPreferredScreenResolution; FbProtocol.Initialize = InitializeDisplay; FbProtocol.SetScreenResolution = SetScreenResolution; /* Register XTOS boot protocol */ return XtLdrProtocol->Protocol.Install(&FbProtocol, &Guid); } /** * Sets custom screen resolution, based on the provided width and height. * * @param Width * Supplies the width of the screen. * * @param Height * Supplies the height of the screen. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS FrameBuffer::SetScreenResolution(IN UINT Width, IN UINT Height) { PEFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInfo; BOOLEAN ModeChanged; EFI_STATUS Status; UINT_PTR Size; UINT Mode; /* Check if framebuffer is initialized */ if(!DisplayInfo.Initialized) { /* Framebuffer not ready to change screen mode */ return STATUS_EFI_NOT_READY; } ModeChanged = FALSE; /* Change screen mode depending on display adapter protocol */ switch(DisplayInfo.Protocol) { case GOP: /* GOP available, check if user specified screen resolution */ if(Width == 0 || Height == 0) { /* No resolution specified, temporarily set lowest supported screen resolution */ Status = DisplayInfo.Driver.Gop->SetMode(DisplayInfo.Driver.Gop, 1); if(Status == STATUS_EFI_SUCCESS) { /* Restore default graphics mode */ Status = DisplayInfo.Driver.Gop->SetMode(DisplayInfo.Driver.Gop, DisplayInfo.DefaultMode); ModeChanged = (Status == STATUS_EFI_SUCCESS) ? TRUE : FALSE; } } else { /* User specified screen resolution, find a corresponding mode */ Mode = 1; while(Mode <= DisplayInfo.Driver.Gop->Mode->MaxMode) { /* Get mode information */ Status = DisplayInfo.Driver.Gop->QueryMode(DisplayInfo.Driver.Gop, Mode, &Size, &ModeInfo); if(Status == STATUS_EFI_SUCCESS && Size >= sizeof(*ModeInfo) && ModeInfo != NULLPTR) { /* Check if match found */ if(ModeInfo->HorizontalResolution == Width && ModeInfo->VerticalResolution == Height) { /* Found corresponding mode, attempt to set it */ Status = DisplayInfo.Driver.Gop->SetMode(DisplayInfo.Driver.Gop, Mode); if(Status == STATUS_EFI_SUCCESS) { /* New mode set correctly, use it */ ModeChanged = TRUE; break; } } } /* Try with next mode */ Mode++; } } break; case UGA: /* Set UGA screen mode, trying to keep current color depth and refresh rate */ Status = DisplayInfo.Driver.Uga->SetMode(DisplayInfo.Driver.Uga, Width, Height, DisplayInfo.ModeInfo.Depth, DisplayInfo.ModeInfo.RefreshRate); if(Status == STATUS_EFI_SUCCESS) { /* New mode set correctly, use it */ ModeChanged = TRUE; } break; default: /* This should never be reached */ break; } if(!ModeChanged) { /* Failed to change screen mode */ XtLdrProtocol->Debug.Print(L"ERROR: Failed to change screen mode to %ux%u (Status Code: 0x%zX)\n", Width, Height, Status); return STATUS_EFI_UNSUPPORTED; } /* Get new screen mode information */ Status = GetModeInformation(); if(Status == STATUS_EFI_SUCCESS) { XtLdrProtocol->Debug.Print(L"Changed screen resolution to %ux%ux%u\n", DisplayInfo.ModeInfo.Width, DisplayInfo.ModeInfo.Height, DisplayInfo.ModeInfo.BitsPerPixel); } /* Return success */ return STATUS_EFI_SUCCESS; } /** * This routine is the entry point of the XT EFI boot loader module. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS XtLdrModuleMain(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { /* Initialize FRAMEBUF module */ return FrameBuffer::InitializeModule(ImageHandle, SystemTable); } ================================================ FILE: boot/xtldr/modules/framebuf/includes/framebuf.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/framebuf/includes/framebuf.hh * DESCRIPTION: EFI Framebuffer support module header file * DEVELOPERS: Rafal Kupiec */ #ifndef __XTLDR_MODULES_FRAMEBUF_HH #define __XTLDR_MODULES_FRAMEBUF_HH #include class FrameBuffer { private: STATIC XTBL_FRAMEBUFFER_INFORMATION DisplayInfo; STATIC XTBL_FRAMEBUFFER_PROTOCOL FbProtocol; STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol; public: STATIC XTCDECL EFI_STATUS GetDisplayDriver(OUT PEFI_GRAPHICS_PROTOCOL Protocol); STATIC XTCDECL EFI_STATUS GetDisplayInformation(OUT PEFI_PHYSICAL_ADDRESS FrameBufferBase, OUT PULONG_PTR FrameBufferSize, OUT PXTBL_FRAMEBUFFER_MODE_INFORMATION ModeInfo); STATIC XTCDECL EFI_STATUS GetPreferredScreenResolution(OUT PUINT PreferredWidth, OUT PUINT PreferredHeight); STATIC XTCDECL EFI_STATUS InitializeDisplay(); STATIC XTCDECL EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable); STATIC XTCDECL EFI_STATUS SetScreenResolution(IN UINT Width, IN UINT Height); private: STATIC EFI_STATUS FindFramebufferAddress(OUT PEFI_PHYSICAL_ADDRESS Address); STATIC XTCDECL VOID GetColorMask(IN UINT EfiMask, OUT PUSHORT ColorSize, OUT PUSHORT ColorShift); STATIC XTCDECL EFI_STATUS GetModeInformation(); STATIC XTCDECL VOID GetPixelInformation(IN PEFI_PIXEL_BITMASK PixelsBitMask); }; #endif /* __XTLDR_MODULES_FRAMEBUF_HH */ ================================================ FILE: boot/xtldr/modules/pecoff/CMakeLists.txt ================================================ # XTLDR PE/COFF image support module PROJECT(XTLDR_PECOFF) # Specify include directories include_directories( ${EXECTOS_SOURCE_DIR}/sdk/xtdk ${XTLDR_PECOFF_SOURCE_DIR}/includes) # Specify list of source code files list(APPEND XTLDR_PECOFF_SOURCE ${XTLDR_PECOFF_SOURCE_DIR}/data.cc ${XTLDR_PECOFF_SOURCE_DIR}/pecoff.cc) # Link module executable add_executable(pecoff ${XTLDR_PECOFF_SOURCE}) # Add linker libraries target_link_libraries(pecoff libxtldr libxtos) # Set proper binary name and install target set_target_properties(pecoff PROPERTIES SUFFIX .efi) set_install_target(pecoff efi/boot/xtldr/modules) # Set module entrypoint and subsystem set_entrypoint(pecoff "XtLdrModuleMain") set_linker_map(pecoff TRUE) set_subsystem(pecoff efi_boot_service_driver) ================================================ FILE: boot/xtldr/modules/pecoff/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/pecoff/globals.cc * DESCRIPTION: Basic PE/COFF executable file format global and static data * DEVELOPERS: Rafal Kupiec */ #include /* XTOS PE/COFF Image Protocol */ XTBL_EXECUTABLE_IMAGE_PROTOCOL PeCoff::PeProtocol; /* EFI XT Loader Protocol */ PXTBL_LOADER_PROTOCOL PeCoff::XtLdrProtocol; ================================================ FILE: boot/xtldr/modules/pecoff/includes/pecoff.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/pecoff/includes/pecoff.hh * DESCRIPTION: Basic PE/COFF executable file format support header * DEVELOPERS: Rafal Kupiec */ #ifndef __XTLDR_PECOFF_HH #define __XTLDR_PECOFF_HH #include /* PE/COFF module for XTLDR */ class PeCoff { private: STATIC XTBL_EXECUTABLE_IMAGE_PROTOCOL PeProtocol; STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol; public: STATIC XTCDECL EFI_STATUS GetEntryPoint(IN PVOID ImagePointer, OUT PVOID *EntryPoint); STATIC XTCDECL EFI_STATUS GetFileSize(IN PVOID ImagePointer, OUT PULONGLONG FileSize); STATIC XTCDECL EFI_STATUS GetImageSize(IN PVOID ImagePointer, OUT PUINT ImageSize); STATIC XTCDECL EFI_STATUS GetMachineType(IN PVOID ImagePointer, OUT PUSHORT MachineType); STATIC XTCDECL EFI_STATUS GetSection(IN PVOID ImagePointer, IN PCHAR SectionName, OUT PULONG *RawData); STATIC XTCDECL EFI_STATUS GetSubSystem(IN PVOID ImagePointer, OUT PUSHORT SubSystem); STATIC XTCDECL EFI_STATUS GetVersion(IN PVOID ImagePointer, OUT PUSHORT Version); STATIC XTCDECL EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable); STATIC XTCDECL EFI_STATUS LoadImage(IN PEFI_FILE_HANDLE FileHandle, IN LOADER_MEMORY_TYPE MemoryType, IN PVOID VirtualAddress, OUT PVOID *ImagePointer); STATIC XTCDECL EFI_STATUS RelocateImage(IN PVOID ImagePointer, IN EFI_VIRTUAL_ADDRESS Address); STATIC XTCDECL EFI_STATUS UnloadImage(IN PVOID ImagePointer); STATIC XTCDECL EFI_STATUS VerifyImage(IN PVOID ImagePointer); private: STATIC XTCDECL EFI_STATUS RelocateLoadedImage(IN PPECOFF_IMAGE_CONTEXT Image); }; #endif /* __XTLDR_PECOFF_HH */ ================================================ FILE: boot/xtldr/modules/pecoff/pecoff.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/pecoff/pecoff.cc * DESCRIPTION: Basic PE/COFF executable file format support module * DEVELOPERS: Rafal Kupiec */ #include /* PE/COFF_O module information */ MODULE_AUTHOR(L"Rafal Kupiec "); MODULE_DESCRIPTION(L"Basic PE/COFF executable file format support"); MODULE_LICENSE(L"GPLv3"); MODULE_VERSION(L"0.1"); /** * Returns the address of the entry point. * * @param ImagePointer * Supplies a pointer to the PE/COFF context structure representing the loaded image. * * @param EntryPoint * Supplies a pointer to the memory area where address of the image entry point will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS PeCoff::GetEntryPoint(IN PVOID ImagePointer, OUT PVOID *EntryPoint) { PPECOFF_IMAGE_CONTEXT Image; /* Get PE/COFF image pointer*/ Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer; /* Validate input data */ if(!Image || !Image->PeHeader) { /* Invalid parameter passed */ return STATUS_EFI_INVALID_PARAMETER; } /* Check PE/COFF image type */ if(Image->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { /* Get entry point from 64-bit optional header */ *EntryPoint = (PUCHAR)Image->VirtualAddress + Image->PeHeader->OptionalHeader64.AddressOfEntryPoint; } else { /* Get entry point from 32-bit optional header */ *EntryPoint = (PUCHAR)Image->VirtualAddress + Image->PeHeader->OptionalHeader32.AddressOfEntryPoint; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Returns the size of the loaded PE/COFF file. * * @param ImagePointer * Supplies a pointer to the PE/COFF context structure representing the loaded image. * * @param ImageSize * Supplies a pointer to the memory area where file size will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS PeCoff::GetFileSize(IN PVOID ImagePointer, OUT PULONGLONG FileSize) { PPECOFF_IMAGE_CONTEXT Image; /* Get PE/COFF image pointer*/ Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer; /* Validate input data */ if(!Image || !Image->ImageSize) { /* Invalid parameter passed */ return STATUS_EFI_INVALID_PARAMETER; } /* Get image size and return success */ *FileSize = Image->FileSize; return STATUS_EFI_NOT_FOUND; } /** * Returns the size of the loaded PE/COFF image. * * @param ImagePointer * Supplies a pointer to the PE/COFF context structure representing the loaded image. * * @param ImageSize * Supplies a pointer to the memory area where image size will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS PeCoff::GetImageSize(IN PVOID ImagePointer, OUT PUINT ImageSize) { PPECOFF_IMAGE_CONTEXT Image; /* Get PE/COFF image pointer*/ Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer; /* Validate input data */ if(!Image || !Image->ImageSize) { /* Invalid parameter passed */ return STATUS_EFI_INVALID_PARAMETER; } /* Get image size and return success */ *ImageSize = Image->ImageSize; return STATUS_EFI_NOT_FOUND; } /** * Returns the machine type of the PE/COFF image. * * @param ImagePointer * Supplies a pointer to the PE/COFF context structure representing the loaded image. * * @param MachineType * Supplies a pointer to the memory area where a value defined for the 'machine' field will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS PeCoff::GetMachineType(IN PVOID ImagePointer, OUT PUSHORT MachineType) { PPECOFF_IMAGE_CONTEXT Image; /* Get PE/COFF image pointer*/ Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer; /* Validate input data */ if(!Image || !Image->PeHeader) { /* Invalid parameter passed */ return STATUS_EFI_INVALID_PARAMETER; } /* Get image machine type and return success */ *MachineType = Image->PeHeader->FileHeader.Machine; return STATUS_EFI_SUCCESS; } /** * Returns an address to the specified section in the PE/COFF image. * * @param ImagePointer * Supplies a pointer to the PE/COFF context structure representing the loaded image. * * @param SectionName * Supplies a name of the requested section. * * @param RawData * Supplies a pointer to the memory area where the address of the requested section will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS PeCoff::GetSection(IN PVOID ImagePointer, IN PCHAR SectionName, OUT PULONG *RawData) { PPECOFF_IMAGE_SECTION_HEADER SectionHeader; PPECOFF_IMAGE_CONTEXT Image; SIZE_T SectionNameLength; USHORT SectionIndex; /* Get PE/COFF image pointer*/ Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer; /* Validate input data */ if(!Image || !Image->PeHeader) { /* Invalid parameter passed */ return STATUS_EFI_INVALID_PARAMETER; } /* Check PE/COFF image type */ if(Image->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { /* Find section header in 64-bit optional header */ SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&Image->PeHeader->OptionalHeader64 + Image->PeHeader->FileHeader.SizeOfOptionalHeader); } else { /* Find section header in 32-bit optional header */ SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&Image->PeHeader->OptionalHeader32 + Image->PeHeader->FileHeader.SizeOfOptionalHeader); } /* Get section name length */ SectionNameLength = XtLdrProtocol->String.Length(SectionName, 0); /* Iterate through all image sections */ for(SectionIndex = 0; SectionIndex < Image->PeHeader->FileHeader.NumberOfSections; SectionIndex++) { /* Check section name */ if(XtLdrProtocol->String.Compare((PCHAR)SectionHeader[SectionIndex].Name, SectionName, SectionNameLength) == 0) { /* Store section address and return */ *RawData = (PULONG)((PUCHAR)Image->Data + SectionHeader[SectionIndex].PointerToRawData); return STATUS_EFI_SUCCESS; } } /* Section not found if reached here */ return STATUS_EFI_NOT_FOUND; } /** * Returns an information about subsystem that is required to run PE/COFF image. * * @param ImagePointer * Supplies a pointer to the PE/COFF context structure representing the loaded image. * * @param SubSystem * Supplies a pointer to the memory area storing a value defined for the 'subsystem' field of the image. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS PeCoff::GetSubSystem(IN PVOID ImagePointer, OUT PUSHORT SubSystem) { PPECOFF_IMAGE_CONTEXT Image; /* Get PE/COFF image pointer*/ Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer; /* Validate input data */ if(!Image || !Image->PeHeader) { /* Invalid parameter passed */ return STATUS_EFI_INVALID_PARAMETER; } /* Check PE/COFF image type */ if(Image->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { /* Get image subsystem from 64-bit optional header */ *SubSystem = Image->PeHeader->OptionalHeader64.Subsystem; } else { /* Get image subsystem from 32-bit optional header */ *SubSystem = Image->PeHeader->OptionalHeader32.Subsystem; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Returns an information about major image version. * * @param ImagePointer * Supplies a pointer to the PE/COFF context structure representing the loaded image. * * @param Version * Supplies a pointer to the memory area storing a major image version. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS PeCoff::GetVersion(IN PVOID ImagePointer, OUT PUSHORT Version) { PPECOFF_IMAGE_CONTEXT Image; /* Get PE/COFF image pointer*/ Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer; /* Validate input data */ if(!Image || !Image->PeHeader) { /* Invalid parameter passed */ return STATUS_EFI_INVALID_PARAMETER; } /* Check PE/COFF image type */ if(Image->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { /* Get image major version from 64-bit optional header */ *Version = Image->PeHeader->OptionalHeader64.MajorImageVersion; } else { /* Get image major version from 32-bit optional header */ *Version = Image->PeHeader->OptionalHeader32.MajorImageVersion; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Initializes PECOFF module by opening XTLDR protocol and installing PECOFF protocol. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS PeCoff::InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { EFI_GUID Guid = XT_PECOFF_IMAGE_PROTOCOL_GUID; EFI_STATUS Status; /* Open the XTLDR protocol */ Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open loader protocol */ return STATUS_EFI_PROTOCOL_ERROR; } /* Set routines available via PE/COFF image protocol */ PeProtocol.GetEntryPoint = GetEntryPoint; PeProtocol.GetFileSize = GetFileSize; PeProtocol.GetImageSize = GetImageSize; PeProtocol.GetMachineType = GetMachineType; PeProtocol.GetSection = GetSection; PeProtocol.GetSubSystem = GetSubSystem; PeProtocol.GetVersion = GetVersion; PeProtocol.LoadImage = LoadImage; PeProtocol.RelocateImage = RelocateImage; PeProtocol.UnloadImage = UnloadImage; PeProtocol.VerifyImage = VerifyImage; /* Register PE/COFF protocol */ return XtLdrProtocol->Protocol.Install(&PeProtocol, &Guid); } /** * Loads a PE/COFF image file. * * @param FileHandle * The handle of the opened portable executable (PE) file. * * @param MemoryType * Supplies the type of memory to be assigned to the memory descriptor. * * @param VirtualAddress * Optional virtual address pointing to the memory area where PE/COFF file will be loaded. * * @param Image * Supplies pointer to the memory area where loaded PE/COFF image context will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS PeCoff::LoadImage(IN PEFI_FILE_HANDLE FileHandle, IN LOADER_MEMORY_TYPE MemoryType, IN PVOID VirtualAddress, OUT PVOID *ImagePointer) { EFI_GUID FileInfoGuid = EFI_FILE_INFO_PROTOCOL_GUID; PPECOFF_IMAGE_SECTION_HEADER SectionHeader; PPECOFF_IMAGE_CONTEXT ImageData; EFI_PHYSICAL_ADDRESS Address; PEFI_FILE_INFO FileInfo; UINT_PTR ReadSize; EFI_STATUS Status; UINT SectionSize; SIZE_T Pages; PUCHAR Data; UINT Index; /* Set required size for getting file information */ ReadSize = sizeof(EFI_FILE_INFO) + 32; /* Allocate necessary amount of memory */ Status = XtLdrProtocol->Memory.AllocatePool(ReadSize, (PVOID *)&FileInfo); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ XtLdrProtocol->Debug.Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status); return Status; } /* First attempt to get file information */ Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo); if(Status == STATUS_EFI_BUFFER_TOO_SMALL) { /* Buffer it too small, but EFI tells the required size, let's reallocate */ XtLdrProtocol->Memory.FreePool(&FileInfo); Status = XtLdrProtocol->Memory.AllocatePool(ReadSize, (PVOID *)&FileInfo); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ XtLdrProtocol->Debug.Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status); return Status; } /* Second attempt to get file information */ Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo); } if(Status != STATUS_EFI_SUCCESS) { /* Unable to get file information */ XtLdrProtocol->Debug.Print(L"ERROR: Failed to get PE/COFF file information (Status Code: 0x%zX)\n", Status); return Status; } /* Allocate memory for storing image data */ Status = XtLdrProtocol->Memory.AllocatePool(sizeof(PECOFF_IMAGE_CONTEXT), (PVOID *)&ImageData); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ XtLdrProtocol->Debug.Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status); return Status; } /* Store file size and memory type, nullify data and free up memory */ ImageData->Data = NULLPTR; ImageData->FileSize = FileInfo->FileSize; ImageData->MemoryType = MemoryType; XtLdrProtocol->Memory.FreePool(FileInfo); /* Calculate number of pages */ Pages = EFI_SIZE_TO_PAGES(ImageData->FileSize); /* Allocate pages */ Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, Pages, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Pages allocation failure */ XtLdrProtocol->Debug.Print(L"ERROR: Pages allocation failure (Status Code: 0x%zX)\n", Status); XtLdrProtocol->Memory.FreePool(ImageData); return Status; } /* Read PE/COFF image */ ReadSize = Pages * EFI_PAGE_SIZE; Data = (PUCHAR)(UINT_PTR)Address; Status = FileHandle->Read(FileHandle, &ReadSize, Data); if(Status != STATUS_EFI_SUCCESS) { /* Failed to read data */ XtLdrProtocol->Debug.Print(L"ERROR: Failed to read PE/COFF image file (Status Code: 0x%zX)\n", Status); XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data); XtLdrProtocol->Memory.FreePool(ImageData); return Status; } /* Extract DOS and PE headers */ ImageData->DosHeader = (PPECOFF_IMAGE_DOS_HEADER)Data; ImageData->PeHeader = (PPECOFF_IMAGE_PE_HEADER)((PUCHAR)Data + ImageData->DosHeader->PeHeaderOffset); /* Validate headers */ Status = PeCoff::VerifyImage(ImageData); if(Status != STATUS_EFI_SUCCESS) { /* Header validation failed, probably broken or invalid PE/COFF image */ XtLdrProtocol->Debug.Print(L"ERROR: Invalid PE/COFF image headers (Status Code: 0x%zX)\n", Status); XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data); XtLdrProtocol->Memory.FreePool(ImageData); return Status; } /* Make sure image is executable */ if (!(ImageData->PeHeader->FileHeader.Characteristics & PECOFF_IMAGE_FILE_EXECUTABLE_IMAGE)) { /* Loaded image is not executable */ XtLdrProtocol->Debug.Print(L"ERROR: Non-executable PE/COFF image loaded\n"); XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data); XtLdrProtocol->Memory.FreePool(ImageData); return STATUS_EFI_LOAD_ERROR; } /* Store image size depending on the PE/COFF image type */ if(ImageData->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { /* Store 64-bit image size */ ImageData->ImageSize = ImageData->PeHeader->OptionalHeader64.SizeOfImage; } else { /* Store 32-bit image size */ ImageData->ImageSize = ImageData->PeHeader->OptionalHeader32.SizeOfImage; } /* Calculate number of image pages */ ImageData->ImagePages = EFI_SIZE_TO_PAGES(ImageData->ImageSize); /* Allocate image pages */ Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, ImageData->ImagePages, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Pages reallocation failure */ XtLdrProtocol->Debug.Print(L"ERROR: Pages reallocation failure (Status Code: 0x%zX)\n", Status); XtLdrProtocol->Memory.FreePool(ImageData); return Status; } /* Store image data and virtual address */ ImageData->Data = (PUCHAR)(UINT_PTR)Address; ImageData->PhysicalAddress = (PVOID)(UINT_PTR)Address; if(VirtualAddress) { /* Virtual address passed to this routine */ ImageData->VirtualAddress = VirtualAddress; } else { /* Virtual address not specified, use physical address */ ImageData->VirtualAddress = (PVOID)(UINT_PTR)Address; } /* Check the PE/COFF image type */ if(ImageData->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { /* Copy all PE32+ sections */ XtLdrProtocol->Memory.CopyMemory(ImageData->Data, Data, ImageData->PeHeader->OptionalHeader64.SizeOfHeaders); /* Find PE32+ section header */ SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&ImageData->PeHeader->OptionalHeader64 + ImageData->PeHeader->FileHeader.SizeOfOptionalHeader); } else { /* Copy all PE32 sections */ XtLdrProtocol->Memory.CopyMemory(ImageData->Data, Data, ImageData->PeHeader->OptionalHeader64.SizeOfHeaders); /* Find PE32 section header */ SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&ImageData->PeHeader->OptionalHeader64 + ImageData->PeHeader->FileHeader.SizeOfOptionalHeader); } /* Load each section into memory */ for(Index = 0; Index < ImageData->PeHeader->FileHeader.NumberOfSections; Index++) { /* Check section raw data size and section virtual size */ if(SectionHeader[Index].SizeOfRawData < SectionHeader[Index].Misc.VirtualSize) { /* Use raw data size if it is smaller than virtual size */ SectionSize = SectionHeader[Index].SizeOfRawData; } else { /* User virtual size otherwise */ SectionSize = SectionHeader[Index].Misc.VirtualSize; } /* Make sure section is available */ if(SectionSize > 0 && SectionHeader[Index].PointerToRawData != 0) { /* Copy section */ XtLdrProtocol->Memory.CopyMemory((PUCHAR)ImageData->Data + SectionHeader[Index].VirtualAddress, Data + SectionHeader[Index].PointerToRawData, SectionSize); } /* Check if raw size is shorter than virtual size */ if(SectionSize < SectionHeader[Index].Misc.VirtualSize) { /* Fill remaining space with zeroes */ XtLdrProtocol->Memory.ZeroMemory((PUCHAR)ImageData->Data + SectionHeader[Index].VirtualAddress + SectionSize, SectionHeader[Index].Misc.VirtualSize - SectionSize); } } /* Free pages */ XtLdrProtocol->Memory.FreePages((EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data, Pages); /* Perform relocation fixups */ Status = PeCoff::RelocateLoadedImage(ImageData); if(Status != STATUS_EFI_SUCCESS) { /* Failed to relocate image */ XtLdrProtocol->Debug.Print(L"ERROR: PE/COFF image relocation failed (Status Code: 0x%zX)\n", Status); return Status; } /* Store image data */ *ImagePointer = ImageData; /* Return SUCCESS */ return STATUS_EFI_SUCCESS; } /** * Relocates PE/COFF image to the specified address. * * @param ImagePointer * Supplies a pointer to the PE/COFF context structure representing the loaded image. * * @param Address * Specifies destination address of memory region, where image should be relocated. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS PeCoff::RelocateImage(IN PVOID ImagePointer, IN EFI_VIRTUAL_ADDRESS Address) { PPECOFF_IMAGE_CONTEXT Image; ULONGLONG ImageBase, OldVirtualAddress; EFI_STATUS Status; /* Get PE/COFF image pointer*/ Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer; /* Store original virtual address */ OldVirtualAddress = (UINT_PTR)Image->VirtualAddress; /* Check PE/COFF image type */ if(Image->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { /* This is 64-bit PE32+, store its image base address */ ImageBase = Image->PeHeader->OptionalHeader64.ImageBase; } else { /* This is 32-bit PE32, store its image base address */ ImageBase = Image->PeHeader->OptionalHeader32.ImageBase; } /* Overwrite virtual address and relocate image once again */ Image->VirtualAddress = (PVOID)(Address - OldVirtualAddress + ImageBase); Status = PeCoff::RelocateLoadedImage(Image); if(Status != STATUS_EFI_SUCCESS) { /* Relocation failed */ return Status; } /* Store new image virtual address */ Image->VirtualAddress = (PVOID)Address; /* Return success */ return STATUS_EFI_SUCCESS; } /** * Relocates a loaded PE/COFF image. * * @param Image * Supplies a pointer to the PE/COFF context structure representing the loaded image. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS PeCoff::RelocateLoadedImage(IN PPECOFF_IMAGE_CONTEXT Image) { PPECOFF_IMAGE_BASE_RELOCATION RelocationDir, RelocationEnd; PPECOFF_IMAGE_DATA_DIRECTORY DataDirectory; USHORT Offset, Type, Count; PUSHORT TypeOffset; ULONGLONG ImageBase; PUINT Address; PULONGLONG LongPtr; PUINT ShortPtr; /* Make sure image is not stripped */ if(Image->PeHeader->FileHeader.Characteristics & PECOFF_IMAGE_FILE_RELOCS_STRIPPED) { /* No relocation information found */ XtLdrProtocol->Debug.Print(L"WARNING: PE/COFF image is stripped and contains no information about relocations\n"); return STATUS_EFI_SUCCESS; } /* Check PE/COFF image type */ if(Image->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { /* Set relocation data directory and image base address */ DataDirectory = &Image->PeHeader->OptionalHeader64.DataDirectory[PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC]; ImageBase = Image->PeHeader->OptionalHeader64.ImageBase; /* Check if loaded 64-bit PE32+ image should be relocated */ if(Image->PeHeader->OptionalHeader64.NumberOfRvaAndSizes <= PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC || DataDirectory->VirtualAddress == 0 || DataDirectory->Size < sizeof(PECOFF_IMAGE_BASE_RELOCATION)) { /* No need to relocate the image */ return STATUS_EFI_SUCCESS; } } else { /* Set relocation data directory and image base address */ DataDirectory = &Image->PeHeader->OptionalHeader32.DataDirectory[PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC]; ImageBase = Image->PeHeader->OptionalHeader32.ImageBase; /* Check if loaded 32-bit PE32 image should be relocated */ if(Image->PeHeader->OptionalHeader32.NumberOfRvaAndSizes <= PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC || DataDirectory->VirtualAddress == 0 || DataDirectory->Size < sizeof(PECOFF_IMAGE_BASE_RELOCATION)) { /* No need to relocate the image */ return STATUS_EFI_SUCCESS; } } /* Set relocation pointers */ RelocationDir = (PPECOFF_IMAGE_BASE_RELOCATION)((ULONG_PTR)Image->Data + DataDirectory->VirtualAddress); RelocationEnd = (PPECOFF_IMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + DataDirectory->Size); /* Do relocations */ while(RelocationDir < RelocationEnd && RelocationDir->SizeOfBlock > 0) { /* Calculate number of relocations needed, address and type offset */ Count = (RelocationDir->SizeOfBlock - sizeof(PECOFF_IMAGE_BASE_RELOCATION)) / sizeof(USHORT); Address = (PUINT)((PUCHAR)Image->Data + RelocationDir->VirtualAddress); TypeOffset = (PUSHORT)((PUCHAR)RelocationDir + sizeof(PECOFF_IMAGE_BASE_RELOCATION)); /* Do relocations */ while(Count--) { /* Calculate offset and relocation type */ Offset = *TypeOffset & 0xFFF; Type = *TypeOffset >> 12; /* Check if end of the loaded address reached */ if((PVOID)(PUSHORT)(Address + Offset) >= (PUCHAR)Image->Data + Image->ImageSize) { /* Do not relocate after the end of loaded image */ break; } /* Make sure we are not going to relocate into .reloc section */ if((ULONG_PTR)(Address + Offset) < (ULONG_PTR)RelocationDir || (ULONG_PTR)(Address + Offset) >= (ULONG_PTR)RelocationEnd) { /* Apply relocation fixup */ switch (Type) { case PECOFF_IMAGE_REL_BASED_ABSOLUTE: /* No relocation required */ break; case PECOFF_IMAGE_REL_BASED_DIR64: /* 64-bit relocation */ LongPtr = (PULONGLONG)((PUCHAR)Address + Offset); *LongPtr = *LongPtr - ImageBase + (UINT_PTR)Image->VirtualAddress; break; case PECOFF_IMAGE_REL_BASED_HIGHLOW: /* 32-bit relocation of hight and low half of address */ ShortPtr = (PUINT)((PUCHAR)Address + Offset); *ShortPtr = *ShortPtr - ImageBase + (UINT_PTR)Image->VirtualAddress; break; default: /* Unknown or unsupported relocation type */ return STATUS_EFI_UNSUPPORTED; } } /* Increment the type offset */ TypeOffset++; } /* Next relocation */ RelocationDir = (PPECOFF_IMAGE_BASE_RELOCATION)((PUCHAR)RelocationDir + RelocationDir->SizeOfBlock); } /* Return SUCCESS */ return STATUS_EFI_SUCCESS; } /** * Unloads a PE/COFF image file and frees allocated memory. * * @param ImagePointer * Supplies a pointer to the PE/COFF context structure representing the loaded image. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS PeCoff::UnloadImage(IN PVOID ImagePointer) { PPECOFF_IMAGE_CONTEXT Image; EFI_STATUS Status; /* Get PE/COFF image pointer*/ Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer; /* Validate input data */ if(!Image || !Image->Data) { /* Invalid parameter passed */ return STATUS_EFI_INVALID_PARAMETER; } /* Free memory allocated for the image */ Status = XtLdrProtocol->Memory.FreePages(Image->ImagePages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Image->Data); Status |= XtLdrProtocol->Memory.FreePool(Image); /* Return status */ return Status; } /** * Validates a PE/COFF image headers. * * @param ImagePointer * Supplies a pointer to the PE/COFF context structure representing the loaded image. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS PeCoff::VerifyImage(IN PVOID ImagePointer) { PPECOFF_IMAGE_CONTEXT Image; /* Get PE/COFF image pointer*/ Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer; /* Validate input data */ if(!Image || !Image->PeHeader) { /* Invalid parameter passed */ return STATUS_EFI_INVALID_PARAMETER; } /* Validate file size */ if(Image->FileSize < sizeof(PECOFF_IMAGE_DOS_HEADER)) { /* PE/COFF image shorter than DOS header, return error*/ return STATUS_EFI_END_OF_FILE; } /* Validate DOS header */ if(Image->DosHeader->Magic != PECOFF_IMAGE_DOS_SIGNATURE) { /* Invalid DOS signature, return error */ return STATUS_EFI_INCOMPATIBLE_VERSION; } /* Validate PE header */ if(Image->PeHeader->Signature != PECOFF_IMAGE_NT_SIGNATURE && Image->PeHeader->Signature != PECOFF_IMAGE_XT_SIGNATURE) { /* Invalid PE signature, return error */ return STATUS_EFI_INCOMPATIBLE_VERSION; } /* Validate optional header */ if(Image->PeHeader->OptionalHeader32.Magic != PECOFF_IMAGE_PE_OPTIONAL_HDR32_MAGIC && Image->PeHeader->OptionalHeader64.Magic != PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { /* Invalid optional header signature, return error */ return STATUS_EFI_INCOMPATIBLE_VERSION; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * This routine is the entry point of the XT EFI boot loader module. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS XtLdrModuleMain(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { /* Initialize PECOFF module */ return PeCoff::InitializeModule(ImageHandle, SystemTable); } ================================================ FILE: boot/xtldr/modules/xtos_o/CMakeLists.txt ================================================ # XT Boot Loader PROJECT(XTLDR_XTOS_O) # Specify include directories include_directories( ${EXECTOS_SOURCE_DIR}/sdk/xtdk ${XTLDR_XTOS_O_SOURCE_DIR}/includes) # Specify list of source code files list(APPEND XTLDR_XTOS_O_SOURCE ${XTLDR_XTOS_O_SOURCE_DIR}/${ARCH}/memory.cc ${XTLDR_XTOS_O_SOURCE_DIR}/data.cc ${XTLDR_XTOS_O_SOURCE_DIR}/xtos.cc) # Link bootloader executable add_executable(xtos_o ${XTLDR_XTOS_O_SOURCE}) # Add linker libraries target_link_libraries(xtos_o libxtos libxtldr) # Set proper binary name and install target set_target_properties(xtos_o PROPERTIES SUFFIX .efi) set_install_target(xtos_o efi/boot/xtldr/modules) # Set module entrypoint and subsystem set_entrypoint(xtos_o "XtLdrModuleMain") set_linker_map(xtos_o TRUE) set_subsystem(xtos_o efi_boot_service_driver) ================================================ FILE: boot/xtldr/modules/xtos_o/amd64/memory.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/amd64/memory.cc * DESCRIPTION: EFI memory management for AMD64 target * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include XTCDECL EFI_STATUS Xtos::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap) { EFI_STATUS Status; /* Build page map */ Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, (PageMap->PageMapLevel > 4) ? MM_P5E_LA57_BASE : MM_PXE_BASE); if(Status != STATUS_EFI_SUCCESS) { /* Failed to build page map */ XtLdrProtocol->Debug.Print(L"Failed to build page map (Status code: %zX)\n", Status); return Status; } /* Map memory for hardware layer */ Status = MapHardwareMemoryPool(PageMap); if(Status != STATUS_EFI_SUCCESS) { /* Failed to map memory for hardware layer */ XtLdrProtocol->Debug.Print(L"Failed to map memory for hardware leyer (Status code: %zX)\n", Status); return Status; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Determines the appropriate EFI memory mapping strategy for the AMD64 architecture. * * @return This routine returns TRUE, what results in an identity mapping. * * @since XT 1.0 */ XTCDECL BOOLEAN Xtos::DetermineMappingStrategy() { /* Use an identity mapping strategy */ return TRUE; } /** * Determines the appropriate paging level (PML) for the AMD64 architecture. * * @param Parameters * A pointer to the wide character string containing the kernel boot parameters. * * @return This routine returns the appropriate page map level (5 if LA57 is enabled, 4 otherwise). * * @since XT 1.0 */ XTCDECL ULONG Xtos::DeterminePagingLevel(IN CONST PWCHAR Parameters) { CPUID_REGISTERS CpuRegisters; /* Prepare CPUID registers to query for STD7 features */ XtLdrProtocol->Memory.ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_VENDOR_STRING; /* Query CPUID */ XtLdrProtocol->Cpu.CpuId(&CpuRegisters); /* Verify if the CPU supports the STD7 feature leaf (0x00000007) */ if(CpuRegisters.Eax >= CPUID_GET_STANDARD7_FEATURES) { /* Prepare CPUID registers to query for LA57 support */ XtLdrProtocol->Memory.ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_STANDARD7_FEATURES; /* Query CPUID */ XtLdrProtocol->Cpu.CpuId(&CpuRegisters); /* Check if eXtended Physical Addressing (XPA) is enabled and if LA57 is supported by the CPU */ if((CpuRegisters.Ecx & CPUID_FEATURES_ECX_LA57) && !(XtLdrProtocol->BootUtils.GetBooleanParameter(Parameters, L"NOXPA"))) { /* Enable LA57 (PML5) */ return 5; } } /* Disable LA57 and use PML4 by default */ return 4; } /** * Builds the actual memory mapping page table and enables paging. This routine exits EFI boot services as well. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap) { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS TrampolineAddress; PXT_TRAMPOLINE_ENTRY TrampolineEntry; ULONG_PTR TrampolineSize; PVOID TrampolineCode; /* Check the configured page map level to set the LA57 state accordingly */ if(PageMap->PageMapLevel == 5) { /* Get the trampoline code information */ XtLdrProtocol->BootUtils.GetTrampolineInformation(TrampolineEnableXpa, &TrampolineCode, &TrampolineSize); if(TrampolineCode == NULLPTR || TrampolineSize == 0) { /* Failed to get trampoline information */ XtLdrProtocol->Debug.Print(L"Failed to get trampoline information\n"); return STATUS_EFI_INVALID_PARAMETER; } /* Set the address of the trampoline code below 1MB */ TrampolineAddress = MM_TRAMPOLINE_ADDRESS; /* Allocate pages for the trampoline */ Status = XtLdrProtocol->Memory.AllocatePages(AllocateAddress, EFI_SIZE_TO_PAGES(TrampolineSize), &TrampolineAddress); if(Status != STATUS_EFI_SUCCESS) { /* Failed to allocate memory for trampoline code */ XtLdrProtocol->Debug.Print(L"Failed to allocate memory for trampoline code (Status code: %zX)\n", Status); return Status; } /* Set the trampoline entry point and copy its code into the allocated buffer */ TrampolineEntry = (PXT_TRAMPOLINE_ENTRY)(UINT_PTR)TrampolineAddress; XtLdrProtocol->Memory.CopyMemory((PVOID)TrampolineEntry, TrampolineCode, TrampolineSize); } /* Exit EFI Boot Services */ XtLdrProtocol->Debug.Print(L"Exiting EFI boot services\n"); Status = XtLdrProtocol->Utils.ExitBootServices(); if(Status != STATUS_EFI_SUCCESS) { /* Failed to exit boot services */ XtLdrProtocol->Debug.Print(L"Failed to exit boot services (Status code: %zX)\n", Status); return STATUS_EFI_ABORTED; } /* Check the configured page map level to set the LA57 state accordingly */ if(PageMap->PageMapLevel == 5) { /* Enable Linear Address 57-bit (LA57) extension */ XtLdrProtocol->Debug.Print(L"Enabling Linear Address 57-bit (LA57)\n"); /* Execute the trampoline to enable LA57 and write PML5 to CR3 */ TrampolineEntry((UINT64)PageMap->PtePointer); } else { /* Disable Linear Address 57-bit (LA57) extension */ XtLdrProtocol->Debug.Print(L"Disabling Linear Address 57-bit (LA57)\n"); /* Write PML4 to CR3 and enable paging */ XtLdrProtocol->Cpu.WriteControlRegister(3, (UINT_PTR)PageMap->PtePointer); XtLdrProtocol->Cpu.WriteControlRegister(0, XtLdrProtocol->Cpu.ReadControlRegister(0) | CR0_PG); } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Maps the page table for hardware layer addess space. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Xtos::MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap) { PHARDWARE_PTE P5eBase, PdeBase, PpeBase, PxeBase; EFI_PHYSICAL_ADDRESS Address; EFI_STATUS Status; ULONG Index; if(PageMap->PageMapLevel == 5) { /* Get P5E (PML5) base address */ P5eBase = (PHARDWARE_PTE)PageMap->PtePointer; /* Check if P5E entry already exists */ if(!P5eBase[(MM_HARDWARE_VA_START >> MM_P5I_SHIFT) & 0x1FF].Valid) { /* No valid P5E, allocate memory */ Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, 1, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, return error */ return Status; } /* Map hardware memory */ XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData); /* Zero fill memory used by P5E */ XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE); /* Make P5E valid */ P5eBase[(MM_HARDWARE_VA_START >> MM_P5I_SHIFT) & 0x1FF].Valid = 1; P5eBase[(MM_HARDWARE_VA_START >> MM_P5I_SHIFT) & 0x1FF].PageFrameNumber = Address / EFI_PAGE_SIZE; P5eBase[(MM_HARDWARE_VA_START >> MM_P5I_SHIFT) & 0x1FF].Writable = 1; /* Set PXE base address */ PxeBase = (PHARDWARE_PTE)(UINT_PTR)Address; } else { /* Set PXE base address based on existing P5E */ PxeBase = (PHARDWARE_PTE)((P5eBase[(MM_HARDWARE_VA_START >> MM_P5I_SHIFT) & 0x1FF].PageFrameNumber) << EFI_PAGE_SHIFT); } } else { /* Get PXE (PML4) base address */ PxeBase = (PHARDWARE_PTE)PageMap->PtePointer; } /* Check if PXE entry already exists */ if(!PxeBase[(MM_HARDWARE_VA_START >> MM_PXI_SHIFT) & 0x1FF].Valid) { /* No valid PXE, allocate memory */ Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, 1, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, return error */ return Status; } /* Map hardware memory */ XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData); /* Zero fill memory used by PXE */ XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE); /* Make PXE valid */ PxeBase[(MM_HARDWARE_VA_START >> MM_PXI_SHIFT) & 0x1FF].Valid = 1; PxeBase[(MM_HARDWARE_VA_START >> MM_PXI_SHIFT) & 0x1FF].PageFrameNumber = Address / EFI_PAGE_SIZE; PxeBase[(MM_HARDWARE_VA_START >> MM_PXI_SHIFT) & 0x1FF].Writable = 1; /* Set PPE base address */ PpeBase = (PHARDWARE_PTE)(UINT_PTR)Address; } else { /* Set PPE base address based on existing PXE */ PpeBase = (PHARDWARE_PTE)((PxeBase[(MM_HARDWARE_VA_START >> MM_PXI_SHIFT) & 0x1FF].PageFrameNumber) << EFI_PAGE_SHIFT); } /* Check if PPE entry already exists */ if(!PpeBase[(MM_HARDWARE_VA_START >> MM_PPI_SHIFT) & 0x1FF].Valid) { /* No valid PPE, allocate memory */ Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, 1, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, return error */ return Status; } /* Map hardware memory */ XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData); /* Zero fill memory used by PPE */ XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE); /* Make PPE valid */ PpeBase[(MM_HARDWARE_VA_START >> MM_PPI_SHIFT) & 0x1FF].Valid = 1; PpeBase[(MM_HARDWARE_VA_START >> MM_PPI_SHIFT) & 0x1FF].PageFrameNumber = Address / EFI_PAGE_SIZE; PpeBase[(MM_HARDWARE_VA_START >> MM_PPI_SHIFT) & 0x1FF].Writable = 1; /* Set PDE base address */ PdeBase = (PHARDWARE_PTE)Address; } else { /* Set PDE base address, based on existing PPE */ PdeBase = (PHARDWARE_PTE)((PpeBase[(MM_HARDWARE_VA_START >> MM_PPI_SHIFT) & 0x1FF].PageFrameNumber) << EFI_PAGE_SHIFT); } /* Loop through 2 PDE entries */ for(Index = 0 ; Index < 2 ; Index++) { /* Check if PDE entry already exists */ if(!PdeBase[((MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF) + Index].Valid) { /* No valid PDE, allocate memory */ Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, 1, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, return error */ return Status; } /* Map hardware memory */ XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData); /* Zero fill memory used by PDE */ XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE); /* Make PDE valid */ PdeBase[((MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF) + Index].Valid = 1; PdeBase[((MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF) + Index].PageFrameNumber = Address / EFI_PAGE_SIZE; PdeBase[((MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF) + Index].Writable = 1; } } /* Return success */ return STATUS_EFI_SUCCESS; } ================================================ FILE: boot/xtldr/modules/xtos_o/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/xtos/data.cc * DESCRIPTION: XTOS module global and static data * DEVELOPERS: Rafal Kupiec */ #include /* XTOS Boot Protocol */ XTBL_BOOT_PROTOCOL Xtos::BootProtocol; /* XTOS PE/COFF Image Protocol */ PXTBL_EXECUTABLE_IMAGE_PROTOCOL Xtos::PeCoffProtocol; /* EFI XT Loader Protocol */ PXTBL_LOADER_PROTOCOL Xtos::XtLdrProtocol; ================================================ FILE: boot/xtldr/modules/xtos_o/i686/memory.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/i686/memory.cc * DESCRIPTION: EFI memory management for i686 target * DEVELOPERS: Rafal Kupiec */ #include XTCDECL EFI_STATUS Xtos::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap) { ULONG_PTR SelfMapAddress; EFI_STATUS Status; /* Initialize self map address */ if(PageMap->PageMapLevel == 3) { /* For PML3 (PAE) use PTE base address */ SelfMapAddress = MM_PTE_BASE; } else { /* For PML2 (PAE disabled) use legacy PDE base address */ SelfMapAddress = MM_PDE_LEGACY_BASE; } /* Build page map */ Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, SelfMapAddress); if(Status != STATUS_EFI_SUCCESS) { /* Failed to build page map */ XtLdrProtocol->Debug.Print(L"Failed to build page map (Status code: %zX)\n", Status); return Status; } /* Map memory for hardware layer */ Status = MapHardwareMemoryPool(PageMap); if(Status != STATUS_EFI_SUCCESS) { /* Failed to map memory for hardware layer */ XtLdrProtocol->Debug.Print(L"Failed to map memory for hardware layer (Status code: %zX)\n", Status); return Status; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Determines the appropriate EFI memory mapping strategy for the i686 architecture. * * @return This routine returns FALSE, what results in a sequential mapping. * * @since XT 1.0 */ XTCDECL BOOLEAN Xtos::DetermineMappingStrategy() { /* Use a sequential mapping strategy */ return FALSE; } /** * Determines the appropriate paging level (PML) for the i686 architecture. * * @param Parameters * A pointer to the wide character string containing the kernel boot parameters. * * @return This routine returns the appropriate page map level (3 if PAE is enabled, 2 otherwise). * * @since XT 1.0 */ XTCDECL ULONG Xtos::DeterminePagingLevel(IN CONST PWCHAR Parameters) { CPUID_REGISTERS CpuRegisters; /* Prepare CPUID registers to query for PAE support */ XtLdrProtocol->Memory.ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES; /* Query CPUID */ XtLdrProtocol->Cpu.CpuId(&CpuRegisters); /* Check if eXtended Physical Addressing (XPA) is enabled and if PAE is supported by the CPU */ if((CpuRegisters.Edx & CPUID_FEATURES_EDX_PAE) && !(XtLdrProtocol->BootUtils.GetBooleanParameter(Parameters, L"NOXPA"))) { /* Enable PAE (PML3) */ return 3; } /* Disable PAE and use PML2 by default */ return 2; } /** * Builds the actual memory mapping page table and enables paging. This routine exits EFI boot services as well. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap) { EFI_STATUS Status; /* Exit EFI Boot Services */ XtLdrProtocol->Debug.Print(L"Exiting EFI boot services\n"); Status = XtLdrProtocol->Utils.ExitBootServices(); if(Status != STATUS_EFI_SUCCESS) { /* Failed to exit boot services */ XtLdrProtocol->Debug.Print(L"Failed to exit boot services (Status code: %zX)\n", Status); return STATUS_EFI_ABORTED; } /* Disable paging */ XtLdrProtocol->Cpu.WriteControlRegister(0, XtLdrProtocol->Cpu.ReadControlRegister(0) & ~CR0_PG); /* Check the configured page map level to set the PAE state accordingly */ if(PageMap->PageMapLevel == 3) { /* Enable Physical Address Extension (PAE) */ XtLdrProtocol->Debug.Print(L"Enabling Physical Address Extension (PAE)\n"); XtLdrProtocol->Cpu.WriteControlRegister(4, XtLdrProtocol->Cpu.ReadControlRegister(4) | CR4_PAE); } else { /* Disable Physical Address Extension (PAE) */ XtLdrProtocol->Debug.Print(L"Disabling Physical Address Extension (PAE)\n"); XtLdrProtocol->Cpu.WriteControlRegister(4, XtLdrProtocol->Cpu.ReadControlRegister(4) & ~CR4_PAE); } /* Write page mappings to CR3 */ XtLdrProtocol->Cpu.WriteControlRegister(3, (UINT_PTR)PageMap->PtePointer); /* Enable paging */ XtLdrProtocol->Cpu.WriteControlRegister(0, XtLdrProtocol->Cpu.ReadControlRegister(0) | CR0_PG); /* Return success */ return STATUS_EFI_SUCCESS; } /** * Maps the page table for hardware layer addess space. * * @param PageMap * Supplies a pointer to the page mapping structure. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Xtos::MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap) { EFI_PHYSICAL_ADDRESS Address; PHARDWARE_LEGACY_PTE LegacyPdeBase; PHARDWARE_MODERN_PTE PdeBase; EFI_STATUS Status; /* Allocate memory */ Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, 1, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, return error */ return Status; } /* Zero fill allocated memory */ XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE); /* Map hardware memory */ XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData); /* Check if PAE is enabled (3-level paging) */ if(PageMap->PageMapLevel == 3) { /* Get PDE base address (PAE enabled) */ PdeBase = (PHARDWARE_MODERN_PTE)(((PHARDWARE_MODERN_PTE)PageMap->PtePointer)[MM_HARDWARE_VA_START >> MM_PPI_SHIFT].PageFrameNumber << MM_PAGE_SHIFT); /* Make PDE valid */ XtLdrProtocol->Memory.ZeroMemory(&PdeBase[(MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF], sizeof(HARDWARE_MODERN_PTE)); PdeBase[(MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF].PageFrameNumber = Address >> MM_PAGE_SHIFT; PdeBase[(MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF].Valid = 1; PdeBase[(MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF].Writable = 1; } else { /* Get PDE base address (PAE disabled) */ LegacyPdeBase = (PHARDWARE_LEGACY_PTE)PageMap->PtePointer; /* Check for a conflicting PDE */ if(LegacyPdeBase[MM_HARDWARE_VA_START >> MM_PDI_LEGACY_SHIFT].Valid) { /* PDE already exists and is valid, nothing to do */ return STATUS_EFI_SUCCESS; } /* Make PDE valid */ XtLdrProtocol->Memory.ZeroMemory(&LegacyPdeBase[MM_HARDWARE_VA_START >> MM_PDI_LEGACY_SHIFT], sizeof(HARDWARE_LEGACY_PTE)); LegacyPdeBase[MM_HARDWARE_VA_START >> MM_PDI_LEGACY_SHIFT].Valid = 1; LegacyPdeBase[MM_HARDWARE_VA_START >> MM_PDI_LEGACY_SHIFT].PageFrameNumber = Address >> MM_PAGE_SHIFT; LegacyPdeBase[MM_HARDWARE_VA_START >> MM_PDI_LEGACY_SHIFT].Writable = 1; } /* Return success */ return STATUS_EFI_SUCCESS; } ================================================ FILE: boot/xtldr/modules/xtos_o/includes/xtos.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/xtos/includes/xtos.hh * DESCRIPTION: XTOS boot protocol support header * DEVELOPERS: Rafal Kupiec */ #ifndef __XTLDR_MODULES_XTOS_HH #define __XTLDR_MODULES_XTOS_HH #include /* XTOS kernel entry point */ typedef VOID (XTAPI *PXT_ENTRY_POINT)(IN PKERNEL_INITIALIZATION_BLOCK BootParameters); /* XTOS trampoline entry point */ typedef VOID (*PXT_TRAMPOLINE_ENTRY)(UINT64 PageMap); /* XTOS module for XTLDR */ class Xtos { private: STATIC XTBL_BOOT_PROTOCOL BootProtocol; STATIC PXTBL_EXECUTABLE_IMAGE_PROTOCOL PeCoffProtocol; STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol; public: STATIC XTCDECL EFI_STATUS BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters); STATIC XTCDECL EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable); private: STATIC XTCDECL EFI_STATUS AddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings, IN PVOID VirtualAddress, IN PVOID PhysicalAddress, IN UINT NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); STATIC XTCDECL EFI_STATUS BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL LOADER_MEMORY_TYPE ConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); STATIC XTCDECL BOOLEAN DetermineMappingStrategy(); STATIC XTCDECL ULONG DeterminePagingLevel(IN CONST PWCHAR Parameters); STATIC XTCDECL EFI_STATUS EnablePaging(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL VOID GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource, IN PEFI_PHYSICAL_ADDRESS FrameBufferBase, IN PULONG_PTR FrameBufferSize, IN PXTBL_FRAMEBUFFER_MODE_INFORMATION FrameBufferModeInfo); STATIC XTCDECL EFI_STATUS GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, IN EFI_PHYSICAL_ADDRESS PhysicalBase, IN PVOID VirtualBase, OUT PLIST_ENTRY MemoryDescriptorList); STATIC XTCDECL EFI_STATUS GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, IN EFI_PHYSICAL_ADDRESS PhysicalBase, IN PVOID VirtualBase, IN PVOID FrameBufferVirtualBase, OUT PLIST_ENTRY SystemResourcesList); STATIC XTCDECL EFI_STATUS GetVirtualAddress(IN PLIST_ENTRY MemoryMappings, IN PVOID PhysicalAddress, OUT PVOID *VirtualAddress); STATIC XTCDECL EFI_STATUS InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL EFI_STATUS InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, IN PVOID *VirtualAddress, IN PXTBL_BOOT_PARAMETERS Parameters); STATIC XTCDECL EFI_STATUS InitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings, IN OUT PVOID *MemoryMapAddress); STATIC XTCDECL EFI_STATUS LoadModule(IN PEFI_FILE_HANDLE BootDir, IN PWCHAR FileName, IN PVOID VirtualAddress, IN LOADER_MEMORY_TYPE MemoryType, OUT PPECOFF_IMAGE_CONTEXT *ImageContext); STATIC XTCDECL EFI_STATUS MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL EFI_STATUS MapVirtualMemory(IN PLIST_ENTRY MemoryMappings, IN UINT_PTR VirtualAddress, IN UINT_PTR PhysicalAddress, IN UINT NumberOfPages, IN OUT PVOID *PtePointer); STATIC XTCDECL EFI_STATUS RunBootSequence(IN PEFI_FILE_HANDLE BootDir, IN PXTBL_BOOT_PARAMETERS Parameters); }; #endif /* __XTLDR_MODULES_XTOS_HH */ ================================================ FILE: boot/xtldr/modules/xtos_o/xtos.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/modules/xtos/xtos.cc * DESCRIPTION: XTOS boot protocol support * DEVELOPERS: Rafal Kupiec */ #include /* XTOS module information */ MODULE_AUTHOR(L"Rafal Kupiec "); MODULE_DESCRIPTION(L"XTOS boot protocol support"); MODULE_DEPENDENCY(L"acpi framebuf pecoff"); MODULE_LICENSE(L"GPLv3"); MODULE_VERSION(L"0.1"); /** * Starts the operating system according to the provided parameters using XTOS boot protocol. * * @param Parameters * Input parameters with detailed system configuration like boot device or kernel path. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Xtos::BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters) { EFI_GUID PeCoffProtocolGuid = XT_PECOFF_IMAGE_PROTOCOL_GUID; EFI_HANDLE DiskHandle, ProtocolHandle; PEFI_FILE_HANDLE FsHandle, BootDir; PWCHAR SystemPath; EFI_STATUS Status; /* Print debug message */ XtLdrProtocol->Debug.Print(L"XTOS boot protocol activated\n"); /* Open the XT PE/COFF protocol */ Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID *)&PeCoffProtocol, &PeCoffProtocolGuid); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open loader protocol */ XtLdrProtocol->Debug.Print(L"ERROR: Unable to load PE/COFF image protocol\n"); return STATUS_EFI_PROTOCOL_ERROR; } /* Check device path */ if(Parameters->DevicePath == NULLPTR) { /* No device path set */ XtLdrProtocol->Debug.Print(L"ERROR: No device path provided, unable to boot system\n"); return STATUS_EFI_INVALID_PARAMETER; } /* Check if system path is set */ if(Parameters->SystemPath != NULLPTR) { /* Make sure system path begins with backslash, the only separator supported by EFI */ if(Parameters->SystemPath[0] == '/') { /* Replace directory separator if needed */ Parameters->SystemPath[0] = '\\'; } /* Validate system path */ SystemPath = &Parameters->SystemPath[1]; while(*SystemPath) { /* Make sure it does not point to any subdirectory and not contains special characters */ if(((*SystemPath | 32) - 'a' >= 26) && ((*SystemPath - '0') >= 10)) { /* Invalid path specified */ XtLdrProtocol->Debug.Print(L"ERROR: System path does not point to the valid XTOS installation\n"); return STATUS_EFI_INVALID_PARAMETER; } /* Check next character in the path */ SystemPath++; } } else { /* Fallback to '/ExectOS' by default */ XtLdrProtocol->Debug.Print(L"WARNING: No system path set, falling back to defaults\n"); Parameters->SystemPath = (PWCHAR)L"\\ExectOS"; } /* Check if kernel file is set */ if(Parameters->KernelFile == NULLPTR) { /* No kernel filename set, fallback to default */ XtLdrProtocol->Debug.Print(L"WARNING: No kernel file specified, falling back to defaults\n"); Parameters->KernelFile = (PWCHAR)L"xtoskrnl.exe"; } /* Check if provided any kernel boot arguments */ if(Parameters->Parameters == NULLPTR) { /* No argument supplied */ Parameters->Parameters = (PWCHAR)L""; } /* Print a debug message */ XtLdrProtocol->Debug.Print(L"[XTOS] ARC Path: %S\n" L"[XTOS] System Path: %S\n" L"[XTOS] Kernel File: %S\n" L"[XTOS] Boot Arguments: %S\n", Parameters->ArcName, Parameters->SystemPath, Parameters->KernelFile, Parameters->Parameters); /* Open EFI volume */ Status = XtLdrProtocol->Disk.OpenVolume(Parameters->DevicePath, &DiskHandle, &FsHandle); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open a volume */ XtLdrProtocol->Debug.Print(L"ERROR: Unable to open boot volume\n"); return Status; } /* System path has to point to the boot directory */ XtLdrProtocol->WideString.Concatenate(Parameters->SystemPath, (PWCHAR)L"\\Boot", 0); /* Open XTOS system boot directory */ Status = FsHandle->Open(FsHandle, &BootDir, Parameters->SystemPath, EFI_FILE_MODE_READ, 0); FsHandle->Close(FsHandle); /* Check if system path directory opened successfully */ if(Status == STATUS_EFI_NOT_FOUND) { /* Directory not found, nothing to load */ XtLdrProtocol->Debug.Print(L"ERROR: System boot directory not found\n"); /* Close volume */ XtLdrProtocol->Disk.CloseVolume(&DiskHandle); return Status; } else if(Status != STATUS_EFI_SUCCESS) { /* Failed to open directory */ XtLdrProtocol->Debug.Print(L"ERROR: Unable to open system boot directory\n"); XtLdrProtocol->Disk.CloseVolume(&DiskHandle); return Status; } /* Start boot sequence */ return RunBootSequence(BootDir, Parameters); } /** * Returns information about frame buffer in XTOS compatible format. * * @param InformationBlock * A pointer to memory area containing XT structure where all the information will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Xtos::GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource, IN PEFI_PHYSICAL_ADDRESS FrameBufferBase, IN PULONG_PTR FrameBufferSize, IN PXTBL_FRAMEBUFFER_MODE_INFORMATION FrameBufferModeInfo) { /* Fill in frame buffer resource */ FrameBufferResource->Header.PhysicalAddress = (PVOID)*FrameBufferBase; FrameBufferResource->Header.ResourceType = SystemResourceFrameBuffer; FrameBufferResource->Header.ResourceSize = sizeof(SYSTEM_RESOURCE_FRAMEBUFFER); FrameBufferResource->BufferSize = *FrameBufferSize; FrameBufferResource->Width = FrameBufferModeInfo->Width; FrameBufferResource->Height = FrameBufferModeInfo->Height; FrameBufferResource->Depth = FrameBufferModeInfo->Depth; FrameBufferResource->BitsPerPixel = FrameBufferModeInfo->BitsPerPixel; FrameBufferResource->PixelsPerScanLine = FrameBufferModeInfo->PixelsPerScanLine; FrameBufferResource->Pitch = FrameBufferModeInfo->Pitch; FrameBufferResource->Pixels.BlueShift = FrameBufferModeInfo->PixelInformation.BlueShift; FrameBufferResource->Pixels.BlueSize = FrameBufferModeInfo->PixelInformation.BlueSize; FrameBufferResource->Pixels.GreenShift = FrameBufferModeInfo->PixelInformation.GreenShift; FrameBufferResource->Pixels.GreenSize = FrameBufferModeInfo->PixelInformation.GreenSize; FrameBufferResource->Pixels.RedShift = FrameBufferModeInfo->PixelInformation.RedShift; FrameBufferResource->Pixels.RedSize = FrameBufferModeInfo->PixelInformation.RedSize; FrameBufferResource->Pixels.ReservedShift = FrameBufferModeInfo->PixelInformation.ReservedShift; FrameBufferResource->Pixels.ReservedSize = FrameBufferModeInfo->PixelInformation.ReservedSize; } XTCDECL EFI_STATUS Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, IN EFI_PHYSICAL_ADDRESS PhysicalBase, IN PVOID VirtualBase, OUT PLIST_ENTRY MemoryDescriptorList) { PLOADER_MEMORY_DESCRIPTOR Descriptor; PXTBL_MEMORY_MAPPING MemoryMapping; PLIST_ENTRY ListEntry; /* Initialize the descriptor pointer to the start of the allocated physical buffer */ Descriptor = (PLOADER_MEMORY_DESCRIPTOR)PhysicalBase; /* Get the first entry from the internal boot loader memory map */ ListEntry = PageMap->MemoryMap.Flink; /* Iterate through the internal memory map and populate the loader descriptor list */ while(ListEntry != &PageMap->MemoryMap) { /* Retrieve the internal memory mapping record from the current list entry */ MemoryMapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry); /* Transfer memory type and address information to the kernel descriptor */ Descriptor->MemoryType = MemoryMapping->MemoryType; Descriptor->BasePage = (UINT_PTR)(MemoryMapping->PhysicalAddress / EFI_PAGE_SIZE); Descriptor->PageCount = (ULONG)MemoryMapping->NumberOfPages; /* Link the entry */ XtLdrProtocol->LinkedList.InsertTail(MemoryDescriptorList, &Descriptor->ListEntry); /* Move to the next slot in the allocated buffer */ Descriptor++; ListEntry = ListEntry->Flink; } /* Convert all physical link pointers in the list to their corresponding virtual addresses */ XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, MemoryDescriptorList, (PVOID)PhysicalBase, VirtualBase); /* Return success */ return STATUS_EFI_SUCCESS; } XTCDECL EFI_STATUS Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, IN EFI_PHYSICAL_ADDRESS PhysicalBase, IN PVOID VirtualBase, IN PVOID FrameBufferVirtualBase, OUT PLIST_ENTRY SystemResourcesList) { XTSTATUS Status; EFI_HANDLE ProtocolHandle; EFI_GUID AcpiGuid = XT_ACPI_PROTOCOL_GUID; EFI_GUID FrameBufGuid = XT_FRAMEBUFFER_PROTOCOL_GUID; PXTBL_ACPI_PROTOCOL AcpiProtocol; PXTBL_FRAMEBUFFER_PROTOCOL FrameBufProtocol; XTBL_FRAMEBUFFER_MODE_INFORMATION FbModeInfo; EFI_PHYSICAL_ADDRESS FbAddress; EFI_PHYSICAL_ADDRESS OriginalPhysicalBase; ULONG_PTR FbSize; PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource; PSYSTEM_RESOURCE_ACPI AcpiResource; /* Save original physical base */ OriginalPhysicalBase = PhysicalBase; AcpiResource = (PSYSTEM_RESOURCE_ACPI)PhysicalBase; XtLdrProtocol->Memory.ZeroMemory(AcpiResource, sizeof(SYSTEM_RESOURCE_ACPI)); /* Load ACPI protocol */ Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&AcpiProtocol, &AcpiGuid); if(Status != STATUS_EFI_SUCCESS) { return Status; } AcpiResource->Header.ResourceType = SystemResourceAcpi; AcpiResource->Header.ResourceSize = sizeof(SYSTEM_RESOURCE_ACPI); /* Get APIC and XSDP/RSDP addresses */ AcpiProtocol->GetApicBase(&AcpiResource->ApicBase); AcpiProtocol->GetAcpiDescriptionPointer(&AcpiResource->Header.PhysicalAddress); /* No need to map ACPI */ AcpiResource->Header.VirtualAddress = 0; XtLdrProtocol->LinkedList.InsertTail(SystemResourcesList, &AcpiResource->Header.ListEntry); /* Close ACPI protocol */ XtLdrProtocol->Protocol.Close(&ProtocolHandle, &AcpiGuid); PhysicalBase = PhysicalBase + sizeof(SYSTEM_RESOURCE_ACPI); FrameBufferResource = (PSYSTEM_RESOURCE_FRAMEBUFFER)PhysicalBase; XtLdrProtocol->Memory.ZeroMemory(FrameBufferResource, sizeof(SYSTEM_RESOURCE_FRAMEBUFFER)); /* Load FrameBuffer protocol */ Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&FrameBufProtocol, &FrameBufGuid); if(Status == STATUS_EFI_SUCCESS) { /* Get FrameBuffer information */ Status = FrameBufProtocol->GetDisplayInformation(&FbAddress, &FbSize, &FbModeInfo); if(Status == STATUS_EFI_SUCCESS) { /* Store information about FrameBuffer device */ GetDisplayInformation(FrameBufferResource, &FbAddress, &FbSize, &FbModeInfo); } } if(Status != STATUS_EFI_SUCCESS) { return Status; } /* Assign the pre-mapped virtual address to the resource block */ FrameBufferResource->Header.VirtualAddress = FrameBufferVirtualBase; XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid); XtLdrProtocol->LinkedList.InsertTail(SystemResourcesList, &FrameBufferResource->Header.ListEntry); /* Convert list pointers to virtual */ XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, SystemResourcesList, (PVOID)OriginalPhysicalBase, VirtualBase); /* Return success */ return STATUS_EFI_SUCCESS; } /** * Checks if APIC is present in the system and finds its base address. * * @param MemoryMappings * Supplies a pointer to linked list containing all memory mappings. * * @return This routine returns an EFI status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) { EFI_GUID AcpiGuid = XT_ACPI_PROTOCOL_GUID; PXTBL_ACPI_PROTOCOL AcpiProtocol; EFI_HANDLE ProtocolHandle; PVOID ApicBaseAddress; EFI_STATUS Status; /* Open ACPI protocol */ Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&AcpiProtocol, &AcpiGuid); if(Status != STATUS_EFI_SUCCESS) { /* ACPI protocol not found */ return Status; } /* Get APIC base address */ Status = AcpiProtocol->GetApicBase(&ApicBaseAddress); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get APIC base address */ return Status; } /* Map APIC base address */ XtLdrProtocol->Memory.MapVirtualMemory(PageMap, APIC_BASE, (ULONGLONG)ApicBaseAddress, 1, LoaderFirmwarePermanent); return STATUS_EFI_SUCCESS; } /** * Initializes and maps the kernel initialization block. * * @param MemoryMappings * Supplies a pointer to linked list containing all memory mappings. * * @param VirtualAddress * Supplies a pointer to the next valid, free and available virtual address. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, IN OUT PVOID *VirtualAddress, IN PXTBL_BOOT_PARAMETERS Parameters) { EFI_PHYSICAL_ADDRESS FbPhysicalAddress, PhysicalBlock, PhysicalDescriptor, PhysicalResources; PVOID FbVirtualAddress, VirtualBlock, VirtualResources, VirtualDescriptor; UINT BlockPages, DescriptorPages, FbPages, ParametersSize, ResourcesPages; XTBL_FRAMEBUFFER_MODE_INFORMATION FbModeInfo; PXTBL_FRAMEBUFFER_PROTOCOL FrameBufProtocol; PKERNEL_INITIALIZATION_BLOCK LoaderBlock; EFI_HANDLE ProtocolHandle; EFI_STATUS Status; ULONG_PTR FbSize; EFI_GUID FrameBufGuid = XT_FRAMEBUFFER_PROTOCOL_GUID; /* Initialize Framebuffer information */ FbPhysicalAddress = 0; FbSize = 0; FbVirtualAddress = NULLPTR; FbPages = 0; /* Calculate size of parameters */ ParametersSize = (XtLdrProtocol->WideString.Length(Parameters->Parameters, 0) + 1) * sizeof(WCHAR); /* Calculate number of pages needed for initialization block */ BlockPages = EFI_SIZE_TO_PAGES(sizeof(KERNEL_INITIALIZATION_BLOCK) + ParametersSize); ResourcesPages = EFI_SIZE_TO_PAGES(sizeof(SYSTEM_RESOURCE_ACPI) + sizeof(SYSTEM_RESOURCE_FRAMEBUFFER)); /* Query Framebuffer size for allocation */ if(XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&FrameBufProtocol, &FrameBufGuid) == STATUS_EFI_SUCCESS) { /* Get FrameBuffer information */ FrameBufProtocol->GetDisplayInformation(&FbPhysicalAddress, &FbSize, &FbModeInfo); XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid); } FbPages = EFI_SIZE_TO_PAGES(FbSize); /* Precommit page map to allocate memory */ XtLdrProtocol->Memory.CommitPageMap(PageMap); /* Calculate number of pages needed for memory descriptor list */ DescriptorPages = EFI_SIZE_TO_PAGES(PageMap->MapSize * sizeof(LOADER_MEMORY_DESCRIPTOR) * 2); /* Allocate memory for the kernel initialization block and boot parameters */ Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, BlockPages, &PhysicalBlock); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, return status code */ return Status; } /* Allocate memory for the system resources data structures */ Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, ResourcesPages, &PhysicalResources); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, return status code */ return Status; } /* Allocate memory for the memory descriptor list */ Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, DescriptorPages, &PhysicalDescriptor); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, return status code */ return Status; } /* Map the Kernel Initialization Block into virtual memory and advance the virtual address pointer */ VirtualBlock = *VirtualAddress; XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)VirtualBlock, PhysicalBlock, BlockPages, LoaderSystemBlock); *VirtualAddress = (PUINT8)*VirtualAddress + (BlockPages * EFI_PAGE_SIZE); /* Map the system resources physical memory into virtual address space and update the allocation pointer */ VirtualResources = *VirtualAddress; XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)VirtualResources, PhysicalResources, ResourcesPages, LoaderFirmwarePermanent); *VirtualAddress = (PUINT8)*VirtualAddress + (ResourcesPages * EFI_PAGE_SIZE); /* Check if a framebuffer was detected and requires memory mapping */ if(FbPages > 0) { /* Map the framebuffer physical memory range into virtual address space */ FbVirtualAddress = *VirtualAddress; XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)FbVirtualAddress, FbPhysicalAddress, FbPages, LoaderFirmwarePermanent); *VirtualAddress = (PUINT8)*VirtualAddress + (FbPages * EFI_PAGE_SIZE); } /* Map the allocated physical memory for memory descriptors into the virtual address space */ VirtualDescriptor = *VirtualAddress; XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)VirtualDescriptor, PhysicalDescriptor, DescriptorPages, LoaderMemoryData); *VirtualAddress = (PUINT8)*VirtualAddress + (DescriptorPages * EFI_PAGE_SIZE); /* Set basic loader block properties */ XtLdrProtocol->Memory.ZeroMemory((PVOID)PhysicalBlock, sizeof(KERNEL_INITIALIZATION_BLOCK) + ParametersSize); LoaderBlock = (PKERNEL_INITIALIZATION_BLOCK)PhysicalBlock; LoaderBlock->BlockSize = sizeof(KERNEL_INITIALIZATION_BLOCK); LoaderBlock->BlockVersion = INITIALIZATION_BLOCK_VERSION; LoaderBlock->ProtocolVersion = BOOT_PROTOCOL_VERSION; /* Set LoaderInformation block properties */ LoaderBlock->LoaderInformation.DbgPrint = (PVOID)XtLdrProtocol->Debug.Print; /* Set FirmwareInformation block properties */ LoaderBlock->FirmwareInformation.FirmwareType = SystemFirmwareEfi; // LoaderBlock->FirmwareInformation.EfiFirmware.EfiVersion = EfiSystemTable->Hdr.Revision; LoaderBlock->FirmwareInformation.EfiFirmware.EfiRuntimeServices = NULLPTR; /* Copy parameters to kernel initialization block */ LoaderBlock->KernelParameters = (PWCHAR)((UINT_PTR)VirtualBlock + sizeof(KERNEL_INITIALIZATION_BLOCK)); XtLdrProtocol->Memory.CopyMemory((PVOID)((UINT_PTR)LoaderBlock + sizeof(KERNEL_INITIALIZATION_BLOCK)), Parameters->Parameters, ParametersSize); /* Commit mappings */ XtLdrProtocol->Memory.CommitPageMap(PageMap); /* Initialize system resources list */ XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->SystemResourcesListHead); Status = GetSystemResourcesList(PageMap, PhysicalResources, VirtualResources, FbVirtualAddress, &LoaderBlock->SystemResourcesListHead); if(Status != STATUS_EFI_SUCCESS) { /* Failed to initialize system resources list, return status code */ return Status; } /* Initialize memory descriptor list */ XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->MemoryDescriptorListHead); Status = GetMemoryDescriptorList(PageMap, PhysicalDescriptor, VirtualDescriptor, &LoaderBlock->MemoryDescriptorListHead); if(Status != STATUS_EFI_SUCCESS) { /* Failed to initialize memory descriptor list, return status code */ return Status; } /* Set boot image size */ LoaderBlock->BootImageSize = (PFN_NUMBER)(((ULONGLONG)*VirtualAddress - KSEG0_BASE) / EFI_PAGE_SIZE); /* Return success */ return STATUS_EFI_SUCCESS; } XTCDECL EFI_STATUS Xtos::InitializeModule(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { EFI_GUID Guid = XT_XTOS_BOOT_PROTOCOL_GUID; EFI_STATUS Status; /* Open the XTLDR protocol */ Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open loader protocol */ return STATUS_EFI_PROTOCOL_ERROR; } /* Set routines available via XTOS boot protocol */ BootProtocol.BootSystem = Xtos::BootSystem; /* Register XTOS boot protocol */ XtLdrProtocol->Boot.RegisterProtocol(L"XTOS", &Guid); /* Install XTOS protocol */ return XtLdrProtocol->Protocol.Install(&BootProtocol, &Guid); } /** * Loads XTOS PE/COFF module. * * @param SystemDir * An EFI handle to the opened system directory containing a module that will be loaded. * * @param FileName * An on disk filename of the module that will be loaded. * * @param VirtualAddress * Optional virtual address pointing to the memory area where PE/COFF file will be loaded. * * @param MemoryType * Supplies the type of memory to be assigned to the memory descriptor. * * @param ImageContext * Supplies pointer to the memory area where loaded PE/COFF image context will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, IN PWCHAR FileName, IN PVOID VirtualAddress, IN LOADER_MEMORY_TYPE MemoryType, OUT PPECOFF_IMAGE_CONTEXT *ImageContext) { PEFI_FILE_HANDLE ModuleHandle; USHORT MachineType, SubSystem; EFI_STATUS Status; /* Print debug message */ XtLdrProtocol->Debug.Print(L"Loading %S ... \n", FileName); /* Open module file */ Status = SystemDir->Open(SystemDir, &ModuleHandle, FileName, EFI_FILE_MODE_READ, 0); if(Status != STATUS_EFI_SUCCESS) { /* Unable to open the file */ XtLdrProtocol->Debug.Print(L"ERROR: Failed to open '%S'\n", FileName); return Status; } /* Load the PE/COFF image file */ Status = PeCoffProtocol->LoadImage(ModuleHandle, MemoryType, VirtualAddress, (PVOID*)ImageContext); if(Status != STATUS_EFI_SUCCESS) { /* Unable to load the file */ XtLdrProtocol->Debug.Print(L"ERROR: Failed to load '%S'\n", FileName); return Status; } /* Close image file */ ModuleHandle->Close(ModuleHandle); /* Check PE/COFF image machine type compatibility */ PeCoffProtocol->GetMachineType(*ImageContext, &MachineType); if(MachineType != _ARCH_IMAGE_MACHINE_TYPE) { /* Machine type mismatch */ XtLdrProtocol->Debug.Print(L"ERROR: Loaded incompatible PE/COFF image (machine type mismatch)\n"); return STATUS_EFI_INCOMPATIBLE_VERSION; } /* Check PE/COFF image subsystem */ PeCoffProtocol->GetSubSystem(*ImageContext, &SubSystem); if(SubSystem != PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_KERNEL && SubSystem != PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_APPLICATION && SubSystem != PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_DRIVER) { XtLdrProtocol->Debug.Print(L"WARNING: Loaded PE/COFF image with non-XT subsystem set\n"); } /* Print debug message */ XtLdrProtocol->Debug.Print(L"Loaded %S at PA: %P, VA: %P\n", FileName, (*ImageContext)->PhysicalAddress, (*ImageContext)->VirtualAddress); /* Return success */ return STATUS_EFI_SUCCESS; } /** * This routine initiates an XTOS boot sequence. * * @param BootDir * An EFI handle to the XTOS boot directory. * * @param Parameters * Input parameters with detailed system configuration like boot device or kernel path. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, IN PXTBL_BOOT_PARAMETERS Parameters) { EFI_GUID LoadedImageGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; EFI_GUID FrameBufGuid = XT_FRAMEBUFFER_PROTOCOL_GUID; PKERNEL_INITIALIZATION_BLOCK KernelParameters; PXTBL_FRAMEBUFFER_PROTOCOL FrameBufProtocol; PPECOFF_IMAGE_CONTEXT ImageContext = NULLPTR; PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol; PVOID VirtualAddress; PXT_ENTRY_POINT KernelEntryPoint; EFI_HANDLE ProtocolHandle; EFI_STATUS Status; XTBL_PAGE_MAPPING PageMap; BOOLEAN IdentityMapping; /* Initialize XTOS startup sequence */ XtLdrProtocol->Debug.Print(L"Initializing XTOS startup sequence\n"); /* Load FrameBuffer protocol */ Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&FrameBufProtocol, &FrameBufGuid); if(Status == STATUS_EFI_SUCCESS) { /* Make sure FrameBuffer is initialized */ FrameBufProtocol->Initialize(); FrameBufProtocol->SetScreenResolution(0, 0); } /* Close FrameBuffer protocol */ XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid); /* Determine whether to use a sequential or an identity mapping strategy */ IdentityMapping = DetermineMappingStrategy(); /* Set base virtual memory area for the kernel mappings */ VirtualAddress = (PVOID)(KSEG0_BASE); /* Initialize virtual memory mappings */ XtLdrProtocol->Memory.InitializePageMap(&PageMap, DeterminePagingLevel(Parameters->Parameters), Size4K); /* Map all EFI memory regions */ Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, &VirtualAddress, IdentityMapping, NULLPTR); if(Status != STATUS_EFI_SUCCESS) { /* Mapping failed */ return Status; } /* Check mapping strategy */ if(IdentityMapping) { /* Adjust virtual address to skip the identity-mapped physical range */ VirtualAddress = (PVOID)((ULONGLONG)VirtualAddress + 0x800000000); } /* Load the kernel */ Status = LoadModule(BootDir, Parameters->KernelFile, VirtualAddress, LoaderSystemCode, &ImageContext); if(Status != STATUS_EFI_SUCCESS) { /* Failed to load the kernel */ return Status; } /* Add kernel image memory mapping */ Status = XtLdrProtocol->Memory.MapVirtualMemory(&PageMap, (ULONGLONG)ImageContext->VirtualAddress, (ULONGLONG)ImageContext->PhysicalAddress, ImageContext->ImagePages, LoaderSystemCode); if(Status != STATUS_EFI_SUCCESS) { return Status; } /* Set next valid virtual address right after the kernel */ VirtualAddress = (PUINT8)VirtualAddress + (ImageContext->ImagePages * EFI_PAGE_SIZE); /* Find and map APIC base address */ Status = InitializeApicBase(&PageMap); if(Status != STATUS_EFI_SUCCESS) { /* Failed to setup kernel initialization block */ XtLdrProtocol->Debug.Print(L"Failed to initialize APIC (Status Code: 0x%zX)\n", Status); return Status; } /* Build page map */ Status = BuildPageMap(&PageMap); if(Status != STATUS_EFI_SUCCESS) { XtLdrProtocol->Debug.Print(L"Failed to build page map (Status code: %zX)\n", Status); return Status; } /* Store virtual address of kernel initialization block for future kernel call */ KernelParameters = (PKERNEL_INITIALIZATION_BLOCK)VirtualAddress; /* Setup and map kernel initialization block */ Status = InitializeLoaderBlock(&PageMap, &VirtualAddress, Parameters); if(Status != STATUS_EFI_SUCCESS) { /* Failed to setup kernel initialization block */ XtLdrProtocol->Debug.Print(L"Failed to setup kernel initialization block (Status Code: 0x%zX)\n", Status); return Status; } /* Get kernel entry point */ PeCoffProtocol->GetEntryPoint(ImageContext, (PVOID*)&KernelEntryPoint); /* Close boot directory handle */ BootDir->Close(BootDir); /* Enable paging */ XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&ImageProtocol, &LoadedImageGuid); Status = EnablePaging(&PageMap); if(Status != STATUS_EFI_SUCCESS) { /* Failed to enable paging */ XtLdrProtocol->Debug.Print(L"Failed to enable paging (Status Code: 0x%zX)\n", Status); return Status; } /* Call XTOS kernel */ XtLdrProtocol->Debug.Print(L"Booting the XTOS kernel\n"); KernelEntryPoint(KernelParameters); /* Return success */ return STATUS_EFI_SUCCESS; } /** * This routine is the entry point of the XT EFI boot loader module. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS XtLdrModuleMain(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { /* Initialize XTOS module */ return Xtos::InitializeModule(ImageHandle, SystemTable); } ================================================ FILE: boot/xtldr/protocol.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/protocol.cc * DESCRIPTION: XT Boot Loader protocol support * DEVELOPERS: Rafal Kupiec */ #include /** * Closes a protocol on a provided handle. * * @param Handle * Supplies a handle for the protocol interface that was previously opened. * * @param ProtocolGuid * Supplies a unique protocol GUID. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Protocol::CloseProtocol(IN PEFI_HANDLE Handle, IN PEFI_GUID ProtocolGuid) { return XtLoader::GetEfiSystemTable()->BootServices->CloseProtocol(Handle, ProtocolGuid, XtLoader::GetEfiImageHandle(), NULLPTR); } /** * Finds a boot protocol for specified system type. * * @param SystemType * Specifies the system type to search for. * * @param BootProtocolGuid * Receives the GUID of the registered boot protocol, that supports specified system. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Protocol::FindBootProtocol(IN PCWSTR SystemType, OUT PEFI_GUID BootProtocolGuid) { PXTBL_KNOWN_BOOT_PROTOCOL ProtocolEntry; PLIST_ENTRY ProtocolListEntry; ProtocolListEntry = BootProtocols.Flink; while(ProtocolListEntry != &BootProtocols) { /* Get boot protocol entry */ ProtocolEntry = CONTAIN_RECORD(ProtocolListEntry, XTBL_KNOWN_BOOT_PROTOCOL, Flink); /* Check if this boot protocol supports specified system */ if(RTL::WideString::CompareWideStringInsensitive(ProtocolEntry->SystemType, SystemType, 0) == 0) { /* Boot protocol matched, return success */ *BootProtocolGuid = ProtocolEntry->Guid; return STATUS_EFI_SUCCESS; } /* Move to the next registered boot protocol */ ProtocolListEntry = ProtocolListEntry->Flink; } /* Boot protocol not found, return error */ return STATUS_EFI_NOT_FOUND; } /** * Returns a linked list of all loaded modules. * * @return This routine returns a pointer to a linked list of all loaded modules. * * @since XT 1.0 * * @todo This is a temporary solution and it should be replaced by a complex API allowing to map modules. */ XTCDECL PLIST_ENTRY Protocol::GetModulesList() { /* Return a pointer to a list of all loaded modules */ return &LoadedModules; } XTCDECL VOID Protocol::InitializeProtocol() { /* Initialize list of loaded modules and boot protocols */ RTL::LinkedList::InitializeListHead(&BootProtocols); RTL::LinkedList::InitializeListHead(&LoadedModules); } /** * Installs XTLDR protocol interface. * * @param Guid * Specifies a unique protocol GUID. * * @param Interface * Supplies a pointer to the protocol interface, or NULLPTR if there is no structure associated. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Protocol::InstallProtocol(IN PVOID Interface, IN PEFI_GUID Guid) { EFI_HANDLE Handle = NULLPTR; /* Install protocol interface */ return XtLoader::GetEfiSystemTable()->BootServices->InstallProtocolInterface(&Handle, Guid, EFI_NATIVE_INTERFACE, Interface); } /** * Loads all necessary modules and invokes boot protocol. * * @param ShortName * Supplies a pointer to a short name of the chosen boot menu entry. * * @param OptionsList * Supplies a pointer to list of options associated with chosen boot menu entry. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Protocol::InvokeBootProtocol(IN PWCHAR ShortName, IN PLIST_ENTRY OptionsList) { EFI_GUID VendorGuid = XT_BOOT_LOADER_PROTOCOL_GUID; XTBL_BOOT_PARAMETERS BootParameters; PXTBL_BOOT_PROTOCOL BootProtocol; PLIST_ENTRY OptionsListEntry; PXTBL_CONFIG_ENTRY Option; EFI_GUID BootProtocolGuid; SIZE_T ModuleListLength; PWCHAR ModulesList; EFI_HANDLE Handle; EFI_STATUS Status; /* Initialize boot parameters and a list of modules */ RTL::Memory::ZeroMemory(&BootParameters, sizeof(XTBL_BOOT_PARAMETERS)); ModulesList = NULLPTR; /* Iterate through all options provided by boot menu entry and propagate boot parameters */ OptionsListEntry = OptionsList->Flink; while(OptionsListEntry != OptionsList) { /* Get option */ Option = CONTAIN_RECORD(OptionsListEntry, XTBL_CONFIG_ENTRY, Flink); /* Look for boot protocol and modules list */ if(RTL::WideString::CompareWideStringInsensitive(Option->Name, L"BOOTMODULES", 0) == 0) { /* Check a length of modules list */ ModuleListLength = RTL::WideString::WideStringLength(Option->Value, 0); Status = Memory::AllocatePool(sizeof(WCHAR) * (ModuleListLength + 1), (PVOID *)&ModulesList); if(Status != STATUS_EFI_SUCCESS) { /* Failed to allocate memory, print error message and return status code */ Debug::Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status); return STATUS_EFI_OUT_OF_RESOURCES; } /* Make a copy of modules list */ RTL::Memory::CopyMemory(ModulesList, Option->Value, sizeof(WCHAR) * (ModuleListLength + 1)); } else if(RTL::WideString::CompareWideStringInsensitive(Option->Name, L"SYSTEMTYPE", 0) == 0) { /* Boot protocol found */ BootParameters.SystemType = Option->Value; } else if(RTL::WideString::CompareWideStringInsensitive(Option->Name, L"SYSTEMPATH", 0) == 0) { /* System path found, get volume device path */ Status = Volume::GetDevicePath(Option->Value, &BootParameters.DevicePath, &BootParameters.ArcName, &BootParameters.SystemPath); if(Status != STATUS_EFI_SUCCESS) { /* Failed to find volume */ Debug::Print(L"ERROR: Failed to find volume device path (Status Code: 0x%zX)\n", Status); return Status; } /* Get EFI compatible system path */ Status = Volume::GetEfiPath(BootParameters.SystemPath, &BootParameters.EfiPath); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get EFI path */ Debug::Print(L"ERROR: Failed to get EFI path (Status Code: 0x%zX)\n", Status); return Status; } } else if(RTL::WideString::CompareWideStringInsensitive(Option->Name, L"KERNELFILE", 0) == 0) { /* Kernel file name found */ BootParameters.KernelFile = Option->Value; } else if(RTL::WideString::CompareWideStringInsensitive(Option->Name, L"INITRDFILE", 0) == 0) { /* Initrd file name found */ BootParameters.InitrdFile = Option->Value; } else if(RTL::WideString::CompareWideStringInsensitive(Option->Name, L"HALFILE", 0) == 0) { /* Hal file name found */ BootParameters.HalFile = Option->Value; } else if(RTL::WideString::CompareWideStringInsensitive(Option->Name, L"PARAMETERS", 0) == 0) { /* Kernel parameters found */ BootParameters.Parameters = Option->Value; } /* Move to the next option entry */ OptionsListEntry = OptionsListEntry->Flink; } /* Load all necessary modules */ Status = LoadModules(ModulesList); if(Status != STATUS_EFI_SUCCESS) { /* Failed to load modules, print error message and return status code */ Debug::Print(L"ERROR: Failed to load XTLDR modules (Status Code: 0x%zX)\n", Status); return STATUS_EFI_NOT_READY; } /* Attempt to get boot protocol GUID */ Status = FindBootProtocol(BootParameters.SystemType, &BootProtocolGuid); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get boot protocol GUID */ Debug::Print(L"ERROR: Unable to find appropriate boot protocol (Status Code: 0x%zX)\n", Status); return STATUS_EFI_UNSUPPORTED; } /* Open boot protocol */ Status = OpenProtocol(&Handle, (PVOID *)&BootProtocol, &BootProtocolGuid); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open boot protocol */ Debug::Print(L"ERROR: Failed to open boot protocol (Status Code: 0x%zX)\n", Status); return Status; } /* Check if chosen operating system should be saved */ if(Configuration::GetBooleanValue(L"KEEPLASTBOOT")) { /* Save chosen operating system in NVRAM */ Status = EfiUtils::SetEfiVariable(&VendorGuid, L"XtLdrLastBootOS", (PVOID)ShortName, RTL::WideString::WideStringLength(ShortName, 0) * sizeof(WCHAR)); if(Status != STATUS_EFI_SUCCESS) { /* Failed to save chosen Operating System */ Debug::Print(L"WARNING: Failed to save chosen Operating System in NVRAM (Status Code: 0x%zX)\n", Status); } } /* Boot Operating System */ return BootProtocol->BootSystem(&BootParameters); } /** * Loads a specified XTLDR module from disk. * * @param ModuleName * Specifies the name of the module to load. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Protocol::LoadModule(IN PWCHAR ModuleName) { EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; PLIST_ENTRY DepsListEntry, ModuleListEntry; EFI_MEMMAP_DEVICE_PATH ModuleDevicePath[2]; PEFI_LOADED_IMAGE_PROTOCOL LoadedImage; PEFI_FILE_HANDLE DirHandle, FsHandle; EFI_HANDLE DiskHandle, ModuleHandle; PPECOFF_IMAGE_SECTION_HEADER SectionHeader; PPECOFF_IMAGE_DOS_HEADER DosHeader; PPECOFF_IMAGE_PE_HEADER PeHeader; PXTBL_MODULE_DEPS ModuleDependency; PXTBL_MODULE_INFO ModuleInfo; WCHAR ModuleFileName[24]; ULONG ModuleNameLength; USHORT SectionIndex; PWCHAR SectionData; SIZE_T ModuleSize; EFI_STATUS Status; PVOID ModuleData; ModuleListEntry = LoadedModules.Flink; while(ModuleListEntry != &LoadedModules) { /* Get module information */ ModuleInfo = CONTAIN_RECORD(ModuleListEntry, XTBL_MODULE_INFO, Flink); if(RTL::WideString::CompareWideStringInsensitive(ModuleInfo->ModuleName, ModuleName, 0) == 0) { /* Module already loaded */ Debug::Print(L"WARNING: Module '%S' already loaded!\n", ModuleName); return STATUS_EFI_SUCCESS; } /* Move to next module */ ModuleListEntry = ModuleListEntry->Flink; } /* Print debug message */ Debug::Print(L"Loading module '%S' ...\n", ModuleName); /* Calculate module name length */ ModuleNameLength = RTL::WideString::WideStringLength(ModuleName, 0) + 1; /* Set module path */ RTL::Memory::CopyMemory(ModuleFileName, ModuleName, ModuleNameLength * sizeof(WCHAR)); RTL::WideString::ConcatenateWideString(ModuleFileName, (PWCHAR)L".EFI", 0); /* Open EFI volume */ Status = Volume::OpenVolume(NULLPTR, &DiskHandle, &FsHandle); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open a volume */ return Status; } /* Open XTLDR modules common directory */ Status = FsHandle->Open(FsHandle, &DirHandle, (PWCHAR)XTBL_MODULES_DIRECTORY_PATH, EFI_FILE_MODE_READ, 0); if(Status != STATUS_EFI_SUCCESS) { /* Modules directory not found, attempt to open XTLDR architecture specific modules directory */ Status = FsHandle->Open(FsHandle, &DirHandle, (PWCHAR)XTBL_ARCH_MODULES_DIRECTORY_PATH, EFI_FILE_MODE_READ, 0); } /* Close FS handle */ FsHandle->Close(FsHandle); /* Check if modules directory opened successfully */ if(Status != STATUS_EFI_SUCCESS) { /* Failed to open directory */ Volume::CloseVolume(&DiskHandle); return Status; } /* Read module file from disk and close directory and EFI volume */ Status = Volume::ReadFile(DirHandle, ModuleFileName, &ModuleData, &ModuleSize); DirHandle->Close(DirHandle); Volume::CloseVolume(&DiskHandle); /* Make sure module file was read successfully */ if(Status != STATUS_EFI_SUCCESS) { /* Failed to read file */ return Status; } /* Allocate memory for module information block */ Status = Memory::AllocatePool(sizeof(XTBL_MODULE_INFO), (PVOID*)&ModuleInfo); if(Status != STATUS_EFI_SUCCESS) { /* Failed to allocate memory */ return Status; } /* Zero module information block */ RTL::Memory::ZeroMemory(ModuleInfo, sizeof(XTBL_MODULE_INFO)); /* Setup PE/COFF EFI image headers */ DosHeader = (PPECOFF_IMAGE_DOS_HEADER)ModuleData; PeHeader = (PPECOFF_IMAGE_PE_HEADER)((PUCHAR)ModuleData + DosHeader->PeHeaderOffset); /* Check PE/COFF image type*/ if(PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { /* Get PE32+ (64-bit) image section headers */ SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&PeHeader->OptionalHeader64 + PeHeader->FileHeader.SizeOfOptionalHeader); } else { /* Get PE32 (32-bit) image section headers */ SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&PeHeader->OptionalHeader32 + PeHeader->FileHeader.SizeOfOptionalHeader); } /* Look for .modinfo section */ for(SectionIndex = 0; SectionIndex < PeHeader->FileHeader.NumberOfSections; SectionIndex++) { if(RTL::String::CompareString((PCHAR)SectionHeader[SectionIndex].Name, ".modinfo", 8) == 0) { /* Module information section found */ SectionData = (PWCHAR)((PUCHAR)ModuleData + SectionHeader[SectionIndex].PointerToRawData); /* Get module information */ Status = GetModuleInformation(SectionData, SectionHeader[SectionIndex].SizeOfRawData, ModuleInfo); if(Status != STATUS_EFI_SUCCESS) { /* Failed to read module information */ return Status; } } } /* Iterate through module dependencies */ DepsListEntry = ModuleInfo->Dependencies.Flink; while(DepsListEntry != &ModuleInfo->Dependencies) { /* Get module dependency information */ ModuleDependency = CONTAIN_RECORD(DepsListEntry, XTBL_MODULE_DEPS, Flink); /* Make sure dependency list contains a valid module name */ if(ModuleDependency->ModuleName == NULLPTR || ModuleDependency->ModuleName[0] == L'\0') { /* Invalid module name found, just skip this step */ break; } /* Load dependency module */ Debug::Print(L"Module '%S' requires '%S' ...\n", ModuleName, ModuleDependency->ModuleName); Status = LoadModule(ModuleDependency->ModuleName); if(Status != STATUS_EFI_SUCCESS) { /* Failed to load module, print error message and return status code */ Debug::Print(L"Failed to load dependency module '%S' (Status Code: 0x%zX)\n", ModuleDependency->ModuleName, Status); return STATUS_EFI_UNSUPPORTED; } /* Move to the next dependency */ DepsListEntry = DepsListEntry->Flink; } /* Setup module device path */ ModuleDevicePath[0].Header.Length[0] = sizeof(EFI_MEMMAP_DEVICE_PATH); ModuleDevicePath[0].Header.Length[1] = sizeof(EFI_MEMMAP_DEVICE_PATH) >> 8; ModuleDevicePath[0].Header.Type = EFI_HARDWARE_DEVICE_PATH; ModuleDevicePath[0].Header.SubType = EFI_HARDWARE_MEMMAP_DP; ModuleDevicePath[0].MemoryType = EfiLoaderData; ModuleDevicePath[0].StartingAddress = (UINT_PTR)ModuleData; ModuleDevicePath[0].EndingAddress = (UINT_PTR)ModuleData + ModuleSize; ModuleDevicePath[1].Header.Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL); ModuleDevicePath[1].Header.Length[1] = sizeof(EFI_DEVICE_PATH_PROTOCOL) >> 8; ModuleDevicePath[1].Header.Type = EFI_END_DEVICE_PATH; ModuleDevicePath[1].Header.SubType = EFI_END_ENTIRE_DP; /* Load EFI image */ Debug::Print(L"Starting module '%S' ...\n", ModuleName); Status = EfiUtils::LoadEfiImage((PEFI_DEVICE_PATH_PROTOCOL)ModuleDevicePath, ModuleData, ModuleSize, &ModuleHandle); if(Status != STATUS_EFI_SUCCESS) { /* Check if caused by secure boot */ if(Status == STATUS_EFI_ACCESS_DENIED && XtLoader::GetSecureBootStatus() >= 1) { /* SecureBoot signature validation failed */ Debug::Print(L"ERROR: SecureBoot signature validation failed, module '%S' will not be loaded\n", ModuleName); } else { /* Failed to load module */ Debug::Print(L"ERROR: Unable to load module '%S' (Status Code: 0x%zX)\n", ModuleName, Status); } /* Return error status code */ return Status; } /* Access module interface for further module type check */ Status = XtLoader::GetEfiSystemTable()->BootServices->OpenProtocol(ModuleHandle, &LIPGuid, (PVOID *)&LoadedImage, XtLoader::GetEfiImageHandle(), NULLPTR, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open LoadedImage protocol */ Debug::Print(L"ERROR: Unable to access module interface (Status Code: 0x%zX)\n", Status); return Status; } /* Some firmwares do not allow to start drivers which are not of 'boot system driver' type, so check it */ if(LoadedImage->ImageCodeType != EfiBootServicesCode) { /* Different type set, probably 'runtime driver', refuse to load it */ Debug::Print(L"ERROR: Loaded module is not a boot system driver\n"); /* Close protocol and skip module */ XtLoader::GetEfiSystemTable()->BootServices->CloseProtocol(LoadedImage, &LIPGuid, LoadedImage, NULLPTR); } /* Allocate memory for module name */ Status = Memory::AllocatePool(ModuleNameLength * sizeof(WCHAR), (PVOID *)&ModuleInfo->ModuleName); if(Status != STATUS_EFI_SUCCESS) { /* Failed to allocate memory for module name, return error */ Debug::Print(L"ERROR: Failed to allocate memory (Status Code: 0x%zX)\n", Status); return Status; } /* Copy module name */ RTL::Memory::CopyMemory(ModuleInfo->ModuleName, ModuleName, ModuleNameLength * sizeof(WCHAR)); /* Save additional module information, not found in '.modinfo' section */ ModuleInfo->ModuleBase = LoadedImage->ImageBase; ModuleInfo->ModuleSize = LoadedImage->ImageSize; ModuleInfo->Revision = LoadedImage->Revision; ModuleInfo->UnloadModule = LoadedImage->Unload; /* Close loaded image protocol */ XtLoader::GetEfiSystemTable()->BootServices->CloseProtocol(LoadedImage, &LIPGuid, LoadedImage, NULLPTR); /* Start EFI image */ Status = EfiUtils::StartEfiImage(ModuleHandle); if(Status != STATUS_EFI_SUCCESS) { /* Failed to start module image */ Debug::Print(L"ERROR: Failed to start module '%S' (Status Code: 0x%zX)\n", ModuleName, Status); return Status; } /* Add module to the list of loaded modules */ RTL::LinkedList::InsertTailList(&LoadedModules, &ModuleInfo->Flink); /* Return success */ return STATUS_EFI_SUCCESS; } /** * Helper routine to load all modules supplied in the configuration file. * * @param ModulesList * Supplies a space separated list of XTLDR modules to load (mostly read from configuration file). * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Protocol::LoadModules(IN PWCHAR ModulesList) { PWCHAR LastModule, Module; EFI_STATUS ReturnStatus, Status; /* Set default return value */ ReturnStatus = STATUS_EFI_SUCCESS; if(ModulesList != NULLPTR) { /* Tokenize provided list of modules */ Module = RTL::WideString::TokenizeWideString(ModulesList, L" ", &LastModule); /* Iterate over all arguments passed to boot loader */ while(Module != NULLPTR) { Status = LoadModule(Module); if(Status != STATUS_EFI_SUCCESS) { /* Failed to load module, print error message and set new return value */ Debug::Print(L"ERROR: Failed to load module '%S' (Status Code: 0x%zX)\n", Module, Status); ReturnStatus = STATUS_EFI_LOAD_ERROR; } /* Take next module from the list */ Module = RTL::WideString::TokenizeWideString(NULLPTR, L" ", &LastModule); } } /* Return success */ return ReturnStatus; } /** * Returns an array of handles that support the requested protocol. * * @param Handles * Supplies the address where a pointer to all handles found for the protocol interface. * * @param Count * Provides a number of the returned handles. * * @param ProtocolGuid * Supplies a pointer to the unique protocol GUID. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Protocol::LocateProtocolHandles(OUT PEFI_HANDLE *Handles, OUT PUINT_PTR Count, IN PEFI_GUID ProtocolGuid) { return XtLoader::GetEfiSystemTable()->BootServices->LocateHandleBuffer(ByProtocol, ProtocolGuid, NULLPTR, Count, Handles); } /** * Locates and opens the requested XT Boot Loader or EFI protocol. * * @param Handle * Supplies the address where a pointer to the handle for the protocol interface. * * @param ProtocolHandler * Supplies the address where a pointer to the opened protocol is returned. * * @param ProtocolGuid * Supplies a pointer to the unique protocol GUID. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Protocol::OpenProtocol(OUT PEFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid) { PEFI_HANDLE Handles = NULLPTR; EFI_STATUS Status; UINT_PTR Count; UINT Index; /* Try to locate the handles */ Status = LocateProtocolHandles(&Handles, &Count, ProtocolGuid); if(Status != STATUS_EFI_SUCCESS) { /* Unable to get handles */ return Status; } /* Check if any handles returned */ if(Count > 0) { /* Iterate through all given handles */ for(Index = 0; Index < Count; Index++) { /* Try to open protocol */ Status = OpenProtocolHandle(Handles[Index], ProtocolHandler, ProtocolGuid); /* Check if successfully opened the loader protocol */ if(Status == STATUS_EFI_SUCCESS) { /* Protocol found and successfully opened */ *Handle = Handles[Index]; break; } } } /* Free handles */ XtLoader::GetEfiSystemTable()->BootServices->FreePool(Handles); /* Make sure the loaded protocol has been found */ if(*ProtocolHandler == NULLPTR) { /* Protocol not found */ return STATUS_EFI_NOT_FOUND; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Opens the requested XT Boot Loader or EFI protocol, if it is supported by the handle. * * @param Handle * Supplies a handle for the protocol interface that is being opened. * * @param ProtocolHandler * Supplies the address where a pointer to the opened protocol is returned. * * @param ProtocolGuid * Supplies a pointer to the unique protocol GUID. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Protocol::OpenProtocolHandle(IN EFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid) { return XtLoader::GetEfiSystemTable()->BootServices->OpenProtocol(Handle, ProtocolGuid, ProtocolHandler, XtLoader::GetEfiImageHandle(), NULLPTR, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); } /** * Registers a known boot protocol for a specified OS. * * @param SystemType * Supplies the type of the OS, such as "LINUX", "XTOS", etc. that is supported by the boot protocol. * * @param BootProtocolGuid * Supplies a pointer to the unique protocol GUID. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Protocol::RegisterBootProtocol(IN PCWSTR SystemType, IN PEFI_GUID BootProtocolGuid) { PXTBL_KNOWN_BOOT_PROTOCOL ProtocolEntry; PLIST_ENTRY ProtocolListEntry; EFI_STATUS Status; ProtocolListEntry = BootProtocols.Flink; while(ProtocolListEntry != &BootProtocols) { /* Get boot protocol entry */ ProtocolEntry = CONTAIN_RECORD(ProtocolListEntry, XTBL_KNOWN_BOOT_PROTOCOL, Flink); /* Check if boot protocol already registered for specified system */ if(RTL::WideString::CompareWideStringInsensitive(ProtocolEntry->SystemType, SystemType, 0) == 0) { /* Boot protocol already registered */ return STATUS_EFI_ABORTED; } /* Move to the next registered boot protocol */ ProtocolListEntry = ProtocolListEntry->Flink; } /* Create new boot protocol entry */ Status = Memory::AllocatePool(sizeof(XTBL_BOOT_PROTOCOL), (PVOID *)&ProtocolEntry); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return STATUS_EFI_OUT_OF_RESOURCES; } /* Set protocol properties and add it to the list */ ProtocolEntry->SystemType = (PWCHAR)SystemType; ProtocolEntry->Guid = *BootProtocolGuid; RTL::LinkedList::InsertTailList(&BootProtocols, &ProtocolEntry->Flink); /* Return success */ return STATUS_EFI_SUCCESS; } /** * Reads information from the '.modinfo' section and populates the module information structure. * * @param SectionData * Supplies a pointer to the module's information section data. * * @param SectionSize * Supplies an expected size of the section data. * * @param ModuleInfo * Supplies a pointer to the module information structure that will be filled by data from module's info section. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Protocol::GetModuleInformation(IN PWCHAR SectionData, IN ULONG SectionSize, OUT PXTBL_MODULE_INFO ModuleInfo) { PXTBL_MODULE_DEPS ModuleDependencies; PXTBL_MODULE_AUTHORS ModuleAuthors; PWCHAR Dependency, Key, LastStr; ULONG Index, Count; EFI_STATUS Status; PWCHAR *Strings; /* Initialize authors and dependencies lists */ RTL::LinkedList::InitializeListHead(&ModuleInfo->Authors); RTL::LinkedList::InitializeListHead(&ModuleInfo->Dependencies); /* Get information strings from '.modinfo' section */ Status = GetModuleInfoStrings(SectionData, SectionSize, &Strings, &Count); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get information strings */ return Status; } /* Parse information strings */ for(Index = 0; Index < Count; Index++) { /* Store the key */ Key = Strings[Index]; /* Find the end of the key and the beginning of the value */ while(*Strings[Index] != L'=' && *Strings[Index] != L'\0' && *Strings[Index] != L'\n') { /* Move to the next character */ Strings[Index]++; } /* Make sure value is NULL-terminated */ *Strings[Index] = L'\0'; Strings[Index]++; /* Parse information string key */ if(RTL::WideString::CompareWideString(Key, L"author", 6) == 0) { /* Allocate memory for module author */ Status = Memory::AllocatePool(sizeof(XTBL_MODULE_AUTHORS), (PVOID*)&ModuleAuthors); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Store module's author */ ModuleAuthors->AuthorName = Strings[Index]; RTL::LinkedList::InsertTailList(&ModuleInfo->Authors, &ModuleAuthors->Flink); } else if(RTL::WideString::CompareWideString(Key, L"description", 11) == 0) { /* Store module's description */ ModuleInfo->ModuleDescription = Strings[Index]; } else if(RTL::WideString::CompareWideString(Key, L"license", 7) == 0) { /* Store module's license */ ModuleInfo->License = Strings[Index]; } else if(RTL::WideString::CompareWideString(Key, L"softdeps", 6) == 0) { /* Tokenize value to get module's single dependency */ Dependency = RTL::WideString::TokenizeWideString(Strings[Index], L" ", &LastStr); while(Dependency != NULLPTR) { /* Allocate memory for module dependency */ Status = Memory::AllocatePool(sizeof(XTBL_MODULE_DEPS), (PVOID*)&ModuleDependencies); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Store module's dependency */ ModuleDependencies->ModuleName = Dependency; RTL::LinkedList::InsertTailList(&ModuleInfo->Dependencies, &ModuleDependencies->Flink); /* Get next dependency from single value if available */ Dependency = RTL::WideString::TokenizeWideString(NULLPTR, L" ", &LastStr); } } else if(RTL::WideString::CompareWideString(Key, L"version", 7) == 0) { /* Store module's version */ ModuleInfo->Version = Strings[Index]; } } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Reads raw data from the '.modinfo' section and populates an array of strings. * * @param SectionData * Supplies a pointer to the module's information section data. * * @param SectionSize * Supplies an expected size of the section data. * * @param ModInfo * Supplies a pointer to memory area, where an array of strings read from the section will be stored. * * @param InfoCount * Supplies a pointer to variable that will receive the number of strings found in the section. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Protocol::GetModuleInfoStrings(IN PWCHAR SectionData, IN ULONG SectionSize, OUT PWCHAR **ModInfo, OUT PULONG InfoCount) { ULONG Count, Index, ArrayIndex; PCWSTR InfoStrings; EFI_STATUS Status; PWCHAR *Array; PWCHAR String; ULONG DataSize; /* Check input parameters */ InfoStrings = SectionData; if(!InfoStrings || !SectionSize) { /* Invalid input parameters */ *ModInfo = NULLPTR; *InfoCount = 0; return STATUS_EFI_INVALID_PARAMETER; } /* Calculate the size of the data based on the size of the section */ DataSize = SectionSize / sizeof(WCHAR); /* Skip zero padding at the beginning */ while(DataSize > 0 && *InfoStrings == L'\0') { InfoStrings++; DataSize--; } /* Make sure there is at least one string available */ if(DataSize < 1) { /* No strings found */ *ModInfo = NULLPTR; *InfoCount = 0; return STATUS_EFI_END_OF_FILE; } /* Count number of strings */ Index = 0; Count = 0; while(Index < DataSize) { /* Found start of a new string */ Count++; /* Go to the end of the string */ while(Index < DataSize && InfoStrings[Index] != L'\0') { Index++; } /* Skip all NULL terminators */ while(Index < DataSize && InfoStrings[Index] == L'\0') { Index++; } } /* Allocate memory for the pointer array and the string data */ Status = Memory::AllocatePool(sizeof(PWCHAR) * (Count + 1) + (DataSize + 1) * sizeof(WCHAR), (PVOID *)&Array); if(Status != STATUS_EFI_SUCCESS) { /* Failed to allocate memory */ return STATUS_EFI_OUT_OF_RESOURCES; } /* The string buffer is located right after the pointer array */ String = (PWCHAR)(Array + Count + 1); /* Copy the raw string data */ RTL::Memory::CopyMemory(String, InfoStrings, DataSize * sizeof(WCHAR)); /* Ensure the entire buffer is NULL-terminated for safety */ String[DataSize] = L'\0'; /* Set the last element of the pointer array to NULLPTR */ Array[Count] = NULLPTR; /* Populate the array with pointers to the strings within the buffer */ Index = 0; ArrayIndex = 0; while(Index < DataSize && ArrayIndex < Count) { /* Set pointer to the beginning of the string */ Array[ArrayIndex++] = &String[Index]; /* Find the end of the current string */ while(Index < DataSize && String[Index] != L'\0') { Index++; } /* Skip all NULL terminators to find the beginning of the next string */ while(Index < DataSize && String[Index] == L'\0') { Index++; } } /* Return array of strings and its size */ *ModInfo = Array; *InfoCount = Count; /* Return success */ return STATUS_EFI_SUCCESS; } /** * This routine installs XTLDR protocol for further usage by modules. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Protocol::InstallXtLoaderProtocol() { EFI_GUID Guid = XT_BOOT_LOADER_PROTOCOL_GUID; /* Set all routines available via loader protocol */ LoaderProtocol.Boot.FindProtocol = FindBootProtocol; LoaderProtocol.Boot.InitializeMenuList = Configuration::InitializeBootMenuList; LoaderProtocol.Boot.InvokeProtocol = InvokeBootProtocol; LoaderProtocol.Boot.RegisterMenu = XtLoader::RegisterBootMenu; LoaderProtocol.Boot.RegisterProtocol = RegisterBootProtocol; LoaderProtocol.BootUtils.GetBooleanParameter = BootUtils::GetBooleanParameter; LoaderProtocol.BootUtils.GetTrampolineInformation = AR::ProcessorSupport::GetTrampolineInformation; LoaderProtocol.Config.GetBooleanValue = Configuration::GetBooleanValue; LoaderProtocol.Config.GetBootOptionValue = Configuration::GetBootOptionValue; LoaderProtocol.Config.GetEditableOptions = Configuration::GetEditableOptions; LoaderProtocol.Config.GetValue = Configuration::GetValue; LoaderProtocol.Config.SetBootOptionValue = Configuration::SetBootOptionValue; LoaderProtocol.Console.ClearLine = Console::ClearLine; LoaderProtocol.Console.ClearScreen = Console::ClearScreen; LoaderProtocol.Console.DisableCursor = Console::DisableCursor; LoaderProtocol.Console.EnableCursor = Console::EnableCursor; LoaderProtocol.Console.Print = Console::Print; LoaderProtocol.Console.QueryMode = Console::QueryMode; LoaderProtocol.Console.ReadKeyStroke = Console::ReadKeyStroke; LoaderProtocol.Console.ResetInputBuffer = Console::ResetInputBuffer; LoaderProtocol.Console.SetAttributes = Console::SetAttributes; LoaderProtocol.Console.SetCursorPosition = Console::SetCursorPosition; LoaderProtocol.Console.Write = Console::Write; LoaderProtocol.Cpu.CpuId = AR::CpuFunctions::CpuId; LoaderProtocol.Cpu.ReadControlRegister = AR::CpuFunctions::ReadControlRegister; LoaderProtocol.Cpu.ReadModelSpecificRegister = AR::CpuFunctions::ReadModelSpecificRegister; LoaderProtocol.Cpu.WriteControlRegister = AR::CpuFunctions::WriteControlRegister; LoaderProtocol.Debug.Print = Debug::Print; LoaderProtocol.Disk.CloseVolume = Volume::CloseVolume; LoaderProtocol.Disk.OpenVolume = Volume::OpenVolume; LoaderProtocol.Disk.ReadFile = Volume::ReadFile; LoaderProtocol.IoPort.Read8 = HL::IoPort::ReadPort8; LoaderProtocol.IoPort.Read16 = HL::IoPort::ReadPort16; LoaderProtocol.IoPort.Read32 = HL::IoPort::ReadPort32; LoaderProtocol.IoPort.Write8 = HL::IoPort::WritePort8; LoaderProtocol.IoPort.Write16 = HL::IoPort::WritePort16; LoaderProtocol.IoPort.Write32 = HL::IoPort::WritePort32; LoaderProtocol.LinkedList.InitializeHead = RTL::LinkedList::InitializeListHead; LoaderProtocol.LinkedList.InsertHead = RTL::LinkedList::InsertHeadList; LoaderProtocol.LinkedList.InsertTail = RTL::LinkedList::InsertTailList; LoaderProtocol.LinkedList.RemoveEntry = RTL::LinkedList::RemoveEntryList; LoaderProtocol.Memory.AllocatePages = Memory::AllocatePages; LoaderProtocol.Memory.AllocatePool = Memory::AllocatePool; LoaderProtocol.Memory.BuildPageMap = Memory::BuildPageMap; LoaderProtocol.Memory.CommitPageMap = Memory::CommitPageMap; LoaderProtocol.Memory.CompareMemory = RTL::Memory::CompareMemory; LoaderProtocol.Memory.CopyMemory = RTL::Memory::CopyMemory; LoaderProtocol.Memory.FreePages = Memory::FreePages; LoaderProtocol.Memory.FreePool = Memory::FreePool; LoaderProtocol.Memory.GetMappingsCount = Memory::GetMappingsCount; LoaderProtocol.Memory.GetMemoryMap = Memory::GetMemoryMap; LoaderProtocol.Memory.GetVirtualAddress = Memory::GetVirtualAddress; LoaderProtocol.Memory.InitializePageMap = Memory::InitializePageMap; LoaderProtocol.Memory.MapEfiMemory = Memory::MapEfiMemory; LoaderProtocol.Memory.MapPage = Memory::MapPage; LoaderProtocol.Memory.MapVirtualMemory = Memory::MapVirtualMemory; LoaderProtocol.Memory.MoveMemory = RTL::Memory::MoveMemory; LoaderProtocol.Memory.PhysicalAddressToVirtual = Memory::PhysicalAddressToVirtual; LoaderProtocol.Memory.PhysicalListToVirtual = Memory::PhysicalListToVirtual; LoaderProtocol.Memory.SetMemory = RTL::Memory::SetMemory; LoaderProtocol.Memory.ZeroMemory = RTL::Memory::ZeroMemory; LoaderProtocol.Protocol.Close = CloseProtocol; LoaderProtocol.Protocol.GetModulesList = GetModulesList; LoaderProtocol.Protocol.Install = InstallProtocol; LoaderProtocol.Protocol.LocateHandles = LocateProtocolHandles; LoaderProtocol.Protocol.Open = OpenProtocol; LoaderProtocol.Protocol.OpenHandle = OpenProtocolHandle; LoaderProtocol.Shell.RegisterCommand = Shell::RegisterCommand; LoaderProtocol.String.Compare = RTL::String::CompareString; LoaderProtocol.String.Length = RTL::String::StringLength; LoaderProtocol.String.ToWideString = RTL::String::StringToWideString; LoaderProtocol.String.Trim = RTL::String::TrimString; LoaderProtocol.Tui.DisplayErrorDialog = TextUi::DisplayErrorDialog; LoaderProtocol.Tui.DisplayInfoDialog = TextUi::DisplayInfoDialog; LoaderProtocol.Tui.DisplayInputDialog = TextUi::DisplayInputDialog; LoaderProtocol.Tui.DisplayProgressDialog = TextUi::DisplayProgressDialog; LoaderProtocol.Tui.UpdateProgressBar = TextUi::UpdateProgressBar; LoaderProtocol.Utils.EnterFirmwareSetup = EfiUtils::EnterFirmwareSetup; LoaderProtocol.Utils.ExitBootServices = EfiUtils::ExitBootServices; LoaderProtocol.Utils.GetConfigurationTable = EfiUtils::GetConfigurationTable; LoaderProtocol.Utils.GetEfiVariable = EfiUtils::GetEfiVariable; LoaderProtocol.Utils.GetRandomValue = EfiUtils::GetRandomValue; LoaderProtocol.Utils.GetSecureBootStatus = EfiUtils::GetSecureBootStatus; LoaderProtocol.Utils.InitializeEntropy = EfiUtils::InitializeEntropy; LoaderProtocol.Utils.LoadEfiImage = EfiUtils::LoadEfiImage; LoaderProtocol.Utils.RebootSystem = EfiUtils::RebootSystem; LoaderProtocol.Utils.SetEfiVariable = EfiUtils::SetEfiVariable; LoaderProtocol.Utils.ShutdownSystem = EfiUtils::ShutdownSystem; LoaderProtocol.Utils.SleepExecution = EfiUtils::SleepExecution; LoaderProtocol.Utils.StartEfiImage = EfiUtils::StartEfiImage; LoaderProtocol.Utils.WaitForEfiEvent = EfiUtils::WaitForEfiEvent; LoaderProtocol.WideString.Compare = RTL::WideString::CompareWideString; LoaderProtocol.WideString.CompareInsensitive = RTL::WideString::CompareWideStringInsensitive; LoaderProtocol.WideString.Concatenate = RTL::WideString::ConcatenateWideString; LoaderProtocol.WideString.Format = RTL::WideString::FormatWideString; LoaderProtocol.WideString.Length = RTL::WideString::WideStringLength; LoaderProtocol.WideString.Tokenize = RTL::WideString::TokenizeWideString; /* Register XTLDR loader protocol */ Debug::Print(L"Registering XT loader protocol\n"); return InstallProtocol(&LoaderProtocol, &Guid); } ================================================ FILE: boot/xtldr/shell.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/shell.cc * DESCRIPTION: XT Boot Loader shell * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Implements the built-in `exit` command. Sets the exit flag to signal the main * shell loop to terminate and return control to the boot menu. * * @param Argc * Supplies the number of arguments provided by the user. * * @param Argv * Supplies a list of arguments provided by the user. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Shell::CommandExit(IN ULONG Argc, IN PWCHAR *Argv) { /* Signal the main shell loop to stop and return to the boot menu */ ExitRequest = TRUE; } /** * Implements the built-in `help` command. Prints a list of available commands alongside their descriptions. * * @param Argc * Supplies the number of arguments provided by the user. * * @param Argv * Supplies a list of arguments provided by the user. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Shell::CommandHelp(IN ULONG Argc, IN PWCHAR *Argv) { PXTBL_SHELL_COMMAND CommandEntry; PLIST_ENTRY ListEntry; /* Print a header line */ Console::Print(L"Available commands:\n\n"); /* Walk the registered commands list */ ListEntry = ShellCommands.Flink; while(ListEntry != &ShellCommands) { /* Retrieve the current command entry */ CommandEntry = CONTAIN_RECORD(ListEntry, XTBL_SHELL_COMMAND, Flink); /* Print the command name in a highlighted color */ Console::SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_WHITE); Console::Print(L" %-12S", CommandEntry->Command); /* Print the description in the default color */ Console::SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); Console::Print(L" %S\n", CommandEntry->Description); /* Advance to the next entry */ ListEntry = ListEntry->Flink; } } /** * Implements the built-in `insmod` command. Loads an XTLDR module by its name. * * @param Argc * Supplies the number of arguments provided by the user. * * @param Argv * Supplies a list of arguments provided by the user. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Shell::CommandInsmod(IN ULONG Argc, IN PWCHAR *Argv) { EFI_STATUS Status; /* Check if the module name was provided */ if(Argc != 2) { /* Print usage message and return */ Console::Print(L"Usage: insmod \n"); return; } /* Load the module */ Status = Protocol::LoadModule(Argv[1]); if(Status != STATUS_EFI_SUCCESS) { /* Failed to load module, print error message */ Console::Print(L"ERROR: Failed to load module '%S' (Status: 0x%llx).\n", Argv[1], Status); } } /** * Implements the built-in `lsmod` command. Lists all loaded XTLDR modules. * * @param Argc * Supplies the number of arguments provided by the user. * * @param Argv * Supplies a list of arguments provided by the user. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Shell::CommandLsmod(IN ULONG Argc, IN PWCHAR *Argv) { PXTBL_MODULE_INFO ModuleInfo; PLIST_ENTRY ModulesList; PLIST_ENTRY ListEntry; /* Print header */ Console::Print(L"Module Name Version Base Address Size\n"); Console::Print(L"----------------------------------------------------------------------\n"); /* Get modules list */ ModulesList = Protocol::GetModulesList(); if(ModulesList == NULLPTR) { /* No modules loaded */ return; } /* Iterate over all loaded modules */ ListEntry = ModulesList->Flink; while(ListEntry != ModulesList) { /* Retrieve the module information */ ModuleInfo = CONTAIN_RECORD(ListEntry, XTBL_MODULE_INFO, Flink); /* Print module information */ Console::Print(L"%-16S %-16S 0x%016llx %llu\n", ModuleInfo->ModuleName, ModuleInfo->Version, (ULONGLONG)ModuleInfo->ModuleBase, ModuleInfo->ModuleSize); /* Advance to the next entry */ ListEntry = ListEntry->Flink; } } /** * Implements the built-in `poweroff` command. Shuts down the machine. * * @param Argc * Supplies the number of arguments provided by the user. * * @param Argv * Supplies a list of arguments provided by the user. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Shell::CommandPoweroff(IN ULONG Argc, IN PWCHAR *Argv) { /* Attempt to power off the machine */ Console::Print(L"Powering off...\n"); EfiUtils::ShutdownSystem(); /* The poweroff call failed, print error message */ Console::Print(L"ERROR: Failed to power off the machine\n"); } /** * Implements the built-in `reboot` command. Performs a normal system restart via the EFI runtime services. * When the '/EFI' parameter is supplied, the routine instead schedules a reboot into the UEFI firmware setup interface. * * @param Argc * Supplies the number of arguments provided by the user. * * @param Argv * Supplies a list of arguments provided by the user. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Shell::CommandReboot(IN ULONG Argc, IN PWCHAR *Argv) { /* Check if the /EFI flag was specified */ if(Argc > 1 && RTL::WideString::CompareWideStringInsensitive(Argv[1], L"/EFI", 0) == 0) { /* Attempt to reboot into firmware setup */ Console::Print(L"Rebooting into UEFI firmware setup...\n"); EfiUtils::EnterFirmwareSetup(); /* The firmware does not support this feature, print error message */ Console::Print(L"ERROR: Reboot into firmware setup interface not supported.\n"); } else { /* Perform a standard system reboot */ Console::Print(L"Rebooting...\n"); EfiUtils::RebootSystem(); /* The reboot call failed, print error message */ Console::Print(L"ERROR: Failed to reboot the machine\n"); } } /** * Implements the built-in `ver` command. Prints the bootloader identification string. * * @param Argc * Supplies the number of arguments provided by the user. * * @param Argv * Supplies a list of arguments provided by the user. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Shell::CommandVersion(IN ULONG Argc, IN PWCHAR *Argv) { /* Check if debugging enabled */ if(DEBUG) { /* Print debug version of XTLDR version string */ Console::Print(L"XTLDR Boot Loader v%d.%d (%s-%s)\n", XTLDR_VERSION_MAJOR, XTLDR_VERSION_MINOR, XTOS_VERSION_DATE, XTOS_VERSION_HASH); } else { /* Print standard XTLDR version string */ Console::Print(L"XTLDR Boot Loader v%d.%d\n", XTLDR_VERSION_MAJOR, XTLDR_VERSION_MINOR); } } /** * Looks up the given command name in the registered shell commands list and invokes the corresponding handler. * * @param Argc * Supplies the number of arguments in the argument vector, including the command name itself. * * @param Argv * Supplies a pointer to the argument vector. First argument is the command name. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Shell::ExecuteCommand(IN ULONG Argc, IN PWCHAR *Argv) { PXTBL_SHELL_COMMAND CommandEntry; PLIST_ENTRY ListEntry; /* Walk through the list of registered shell commands */ ListEntry = ShellCommands.Flink; while(ListEntry != &ShellCommands) { /* Retrieve the shell command entry from the list node */ CommandEntry = CONTAIN_RECORD(ListEntry, XTBL_SHELL_COMMAND, Flink); /* Perform a case-insensitive comparison against the command name */ if(RTL::WideString::CompareWideStringInsensitive(CommandEntry->Command, Argv[0], 0) == 0) { /* Command matches, invoke its handler and return */ CommandEntry->Handler(Argc, Argv); return; } /* Advance to the next registered command */ ListEntry = ListEntry->Flink; } /* No matching command was found, print error message */ Console::Print(L"ERROR: '%S' is not recognized as a valid command.\n", Argv[0]); } /** * Splits the supplied raw command line string into an argument count and an argument vector suitable * for command dispatch. The input string is tokenized by whitespace. * * @param CommandLine * Supplies a mutable wide-character string containing the raw command line. * * @param Argc * Receives the number of arguments found in the command line. * * @param Argv * Receives a pointer to an allocated array of wide-character string pointers, one for each argument. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Shell::ParseCommand(IN PWCHAR CommandLine, OUT PULONG Argc, OUT PWCHAR **Argv) { PWCHAR *ArgumentVector, TempLine; ULONG ArgumentCount; EFI_STATUS Status; /* Initialize argument count */ ArgumentCount = 0; /* Count the tokens to determine the size of the argument vector */ TempLine = CommandLine; while(*TempLine != L'\0') { /* Skip leading spaces */ while(*TempLine == L' ') { /* Move to the next character */ TempLine++; } /* Check if the end of the string was reached */ if(*TempLine == L'\0') { /* End of the string, break the loop */ break; } /* One more argument found */ ArgumentCount++; /* Skip the characters of the token */ while(*TempLine != L'\0' && *TempLine != L' ') { /* Move to the next character */ TempLine++; } } /* Check if the command line was empty */ if(ArgumentCount == 0) { /* Set argument count and vector to zero and NULL */ *Argc = 0; *Argv = NULLPTR; /* Return success */ return STATUS_EFI_SUCCESS; } /* Allocate memory for the argument vector */ Status = Memory::AllocatePool(ArgumentCount * sizeof(PWCHAR), (PVOID *)&ArgumentVector); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, return status code */ return Status; } /* Reset argument count and temp line */ ArgumentCount = 0; TempLine = CommandLine; /* Walk through the command line */ while(*TempLine != L'\0') { /* Skip leading whitespace */ while(*TempLine == L' ') { /* Move to the next character */ TempLine++; } /* Check if the end of the string was reached */ if(*TempLine == L'\0') { /* End of string reached, break the loop */ break; } /* Record token */ ArgumentVector[ArgumentCount] = TempLine; ArgumentCount++; /* Advance past the token characters */ while(*TempLine != L'\0' && *TempLine != L' ') { /* Move to the next character */ TempLine++; } /* Check if token was NULL-terminated */ if(*TempLine != L'\0') { /* NULL-terminate the token and move to the next character */ *TempLine = L'\0'; TempLine++; } } /* Return results to the caller */ *Argc = ArgumentCount; *Argv = ArgumentVector; return STATUS_EFI_SUCCESS; } /** * Prints XTLDR shell prompt. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Shell::PrintPrompt() { /* Set prompt color */ Console::SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_YELLOW); /* Print prompt at the start of the line */ Console::Print(L"\rXTLDR> "); /* Reset standard shell colors */ Console::SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); } /** * Prints the whole prompt line, including the current command line and the cursor position. * * @param Buffer * Supplies a pointer to the buffer containing the command line. * * @param BufferLength * Supplies the buffer text length. * * @param CursorPosition * Supplies the current cursor position. * * @param PreviousBufferLength * Supplies the previous buffer text length to clear artifacts. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Shell::PrintPromptLine(IN PWCHAR Buffer, IN ULONG BufferLength, IN ULONG CursorPosition, IN ULONG PreviousBufferLength) { INT32 TargetX, TargetY; WCHAR SavedChar; ULONG Index; /* Print the prompt */ PrintPrompt(); /* Temporarily truncate the string to capture cursor position */ SavedChar = Buffer[CursorPosition]; Buffer[CursorPosition] = L'\0'; /* Print up to the cursor position */ Console::Print(L"%S", Buffer); /* Capture target cursor coordinates from the EFI text mode structure */ TargetX = XtLoader::GetEfiSystemTable()->ConOut->Mode->CursorColumn; TargetY = XtLoader::GetEfiSystemTable()->ConOut->Mode->CursorRow; /* Restore the character and print the remainder of the buffer */ Buffer[CursorPosition] = SavedChar; Console::Print(L"%S", Buffer + CursorPosition); /* Check if the previous buffer was longer than the current one */ if(PreviousBufferLength > BufferLength) { /* Clear artifacts from the previous longer line */ for(Index = 0; Index < (PreviousBufferLength - BufferLength); Index++) { /* Print a white space */ Console::Print(L" "); } } /* Move the cursor back to the correct target position */ Console::SetCursorPosition(TargetX, TargetY); } /** * Reads a complete line of input from the shell console into the supplied buffer. * * @param Buffer * Supplies a pointer to a wide-character buffer that receives the entered command line. * * @param BufferSize * Supplies the capacity of the buffer, in wide characters. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Shell::ReadCommand(OUT PWCHAR Buffer, IN ULONG BufferSize) { ULONG BufferLength, CursorPosition, OldBufferLength; UINT_PTR EventIndex; EFI_INPUT_KEY Key; /* Start with an empty buffer */ CursorPosition = 0; BufferLength = 0; Buffer[0] = L'\0'; /* Reset history index */ HistoryIndex = HistoryCount; /* Read characters until the user submits the command line */ while(TRUE) { /* Wait until a key event is available */ EfiUtils::WaitForEfiEvent(1, &(XtLoader::GetEfiSystemTable()->ConIn->WaitForKey), &EventIndex); /* Read the keystroke from the input device */ Console::ReadKeyStroke(&Key); /* Capture the previous line length to wipe possible artifacts */ OldBufferLength = BufferLength; /* Check the keystroke */ if(Key.UnicodeChar == 0x0D) { /* ENTER key pressed, terminate the buffer and move to a new line */ Buffer[BufferLength] = L'\0'; Console::Print(L"\n"); /* Check if the buffer is not empty */ if(BufferLength > 0) { /* Check if the history is not full */ if(HistoryCount < XTBL_SH_HISTORY_ENTRIES) { /* Store command in history and increment history count */ RTL::Memory::CopyMemory(History[HistoryCount], Buffer, (BufferLength + 1) * sizeof(WCHAR)); HistoryCount++; } else { /* Shift history entries to fit new command */ RTL::Memory::MoveMemory(History[0], History[1], (XTBL_SH_HISTORY_ENTRIES - 1) * XTBL_SH_MAX_LINE_LENGTH * sizeof(WCHAR)); RTL::Memory::CopyMemory(History[XTBL_SH_HISTORY_ENTRIES - 1], Buffer, (BufferLength + 1) * sizeof(WCHAR)); } } /* Return the command line to the caller */ return; } else if(Key.ScanCode == 0x01) { /* UP key pressed, go back in history */ if(HistoryIndex > 0) { /* Decrement history index */ HistoryIndex--; /* Copy history entry to buffer and update cursor position */ BufferLength = RTL::WideString::WideStringLength(History[HistoryIndex], XTBL_SH_MAX_LINE_LENGTH - 1); RTL::Memory::CopyMemory(Buffer, History[HistoryIndex], (BufferLength + 1) * sizeof(WCHAR)); CursorPosition = BufferLength; /* Reprint the prompt line */ PrintPromptLine(Buffer, BufferLength, CursorPosition, OldBufferLength); } /* Continue to the next iteration */ continue; } else if(Key.ScanCode == 0x02) { /* DOWN key pressed, go forward in history */ if(HistoryIndex < HistoryCount) { /* Increment history index */ HistoryIndex++; /* Check if we are at the end of history */ if(HistoryIndex == HistoryCount) { /* End of history, show empty prompt */ Buffer[0] = L'\0'; BufferLength = 0; CursorPosition = 0; } else { /* Copy history entry to buffer and update cursor position */ BufferLength = RTL::WideString::WideStringLength(History[HistoryIndex], XTBL_SH_MAX_LINE_LENGTH - 1); RTL::Memory::CopyMemory(Buffer, History[HistoryIndex], (BufferLength + 1) * sizeof(WCHAR)); CursorPosition = BufferLength; } /* Reprint the prompt line */ PrintPromptLine(Buffer, BufferLength, CursorPosition, OldBufferLength); } /* Continue to the next iteration */ continue; } else if(Key.ScanCode == 0x03) { /* RIGHT key pressed, move cursor right */ if(CursorPosition < BufferLength) { /* Increment cursor position */ CursorPosition++; /* Reprint the prompt line */ PrintPromptLine(Buffer, BufferLength, CursorPosition, OldBufferLength); } /* Continue to the next iteration */ continue; } else if(Key.ScanCode == 0x04) { /* LEFT key pressed, move cursor left */ if(CursorPosition > 0) { /* Decrement cursor position */ CursorPosition--; /* Reprint the prompt line */ PrintPromptLine(Buffer, BufferLength, CursorPosition, OldBufferLength); } /* Continue to the next iteration */ continue; } else if(Key.ScanCode == 0x05) { /* HOME key pressed, move cursor to beginning */ if (CursorPosition > 0) { /* Set cursor position to beginning of the line and reprint the prompt line */ CursorPosition = 0; PrintPromptLine(Buffer, BufferLength, CursorPosition, OldBufferLength); } /* Continue to the next iteration */ continue; } else if(Key.ScanCode == 0x06) { /* END key pressed, move cursor to end */ if (CursorPosition < BufferLength) { /* Set cursor position to end of the line and reprint the prompt line */ CursorPosition = BufferLength; PrintPromptLine(Buffer, BufferLength, CursorPosition, OldBufferLength); } /* Continue to the next iteration */ continue; } else if(Key.ScanCode == 0x17) { /* ESC key pressed, discard the current input, move to a new line and reprint the prompt */ Buffer[0] = L'\0'; Console::Print(L"\n"); PrintPrompt(); /* Reset cursor position, buffer length and history index */ CursorPosition = 0; BufferLength = 0; HistoryIndex = HistoryCount; /* Continue reading the command line */ continue; } else if(Key.ScanCode == 0x08) { /* DELETE key pressed, remove character at cursor */ if(CursorPosition < BufferLength) { /* Move memory to remove the character at cursor */ RTL::Memory::MoveMemory(Buffer + CursorPosition, Buffer + CursorPosition + 1, (BufferLength - CursorPosition) * sizeof(WCHAR)); /* Decrement buffer length and reprint the prompt line */ BufferLength--; PrintPromptLine(Buffer, BufferLength, CursorPosition, OldBufferLength); } /* Continue to the next iteration */ continue; } else if(Key.UnicodeChar == 0x08) { /* BACKSPACE key pressed, delete character before cursor */ if(CursorPosition > 0) { /* Move memory to remove the character before cursor */ RTL::Memory::MoveMemory(Buffer + CursorPosition - 1, Buffer + CursorPosition, (BufferLength - CursorPosition + 1) * sizeof(WCHAR)); /* Decrement cursor position and buffer length */ CursorPosition--; BufferLength--; /* Reprint the prompt line */ PrintPromptLine(Buffer, BufferLength, CursorPosition, OldBufferLength); } /* Continue reading the command line */ continue; } else if(Key.UnicodeChar == 0) { /* Ignore non-printable characters */ continue; } /* Make sure there is room in the buffer (reserve one slot for NULL terminator) */ if(BufferLength < BufferSize - 1) { /* Insert character in the middle or end of the buffer */ RTL::Memory::MoveMemory(Buffer + CursorPosition + 1, Buffer + CursorPosition, (BufferLength - CursorPosition + 1) * sizeof(WCHAR)); Buffer[CursorPosition] = Key.UnicodeChar; /* Increment cursor position and buffer length */ CursorPosition++; BufferLength++; /* Reprint the prompt line */ PrintPromptLine(Buffer, BufferLength, CursorPosition, OldBufferLength); } } } /** * Registers a new command in the XTLDR shell. * * @param Command * Supplies the command keyword that the user types at the shell prompt. * * @param Description * Supplies a short help string displayed by the 'help' command. * * @param Handler * Supplies a pointer to the function that implements the command. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Shell::RegisterCommand(IN PCWSTR Command, IN PCWSTR Description, IN PBL_SHELL_COMMAND Handler) { PXTBL_SHELL_COMMAND CommandEntry; PLIST_ENTRY ListEntry; EFI_STATUS Status; /* Verify that a command with this name has not already been registered */ ListEntry = ShellCommands.Flink; while(ListEntry != &ShellCommands) { /* Retrieve the existing shell command entry */ CommandEntry = CONTAIN_RECORD(ListEntry, XTBL_SHELL_COMMAND, Flink); /* Compare command names case-insensitively */ if(RTL::WideString::CompareWideStringInsensitive(CommandEntry->Command, Command, 0) == 0) { /* Duplicate command name, return error */ return STATUS_EFI_INVALID_PARAMETER; } /* Advance to the next entry */ ListEntry = ListEntry->Flink; } /* Allocate memory for the new command entry */ Status = Memory::AllocatePool(sizeof(XTBL_SHELL_COMMAND), (PVOID *)&CommandEntry); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, return error */ return STATUS_EFI_OUT_OF_RESOURCES; } /* Populate the new command entry */ CommandEntry->Command = (PWCHAR)Command; CommandEntry->Description = (PWCHAR)Description; CommandEntry->Handler = Handler; /* Append the command to the global shell commands list */ RTL::LinkedList::InsertTailList(&ShellCommands, &CommandEntry->Flink); /* Return success */ return STATUS_EFI_SUCCESS; } /** * Registers all built-in shell commands that are provided by the XTLDR. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Shell::RegisterBuiltinCommands() { /* Register all built-in shell commands */ RegisterCommand(L"exit", L"Exits the shell and returns to the boot menu", CommandExit); RegisterCommand(L"help", L"Displays a list of all available shell commands", CommandHelp); RegisterCommand(L"insmod", L"Loads a specific XTLDR module", CommandInsmod); RegisterCommand(L"lsmod", L"Displays a list of loaded modules", CommandLsmod); RegisterCommand(L"poweroff", L"Shuts down the machine", CommandPoweroff); RegisterCommand(L"reboot", L"Reboots the machine (/EFI to enter firmware setup)", CommandReboot); RegisterCommand(L"ver", L"Displays the boot loader version information", CommandVersion); } /** * Initializes the command list, registers the built-in commands and enters an interactive XTLDR shell loop. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID Shell::StartLoaderShell() { WCHAR CommandLine[XTBL_SH_MAX_LINE_LENGTH]; PWCHAR *ArgumentVector; ULONG ArgumentCount; EFI_STATUS Status; /* Initialize console */ Console::InitializeConsole(); /* Initialize the shell commands list */ RTL::LinkedList::InitializeListHead(&ShellCommands); /* Register all built-in commands */ RegisterBuiltinCommands(); /* Clear the shell exit request flag */ ExitRequest = FALSE; /* Main XTLDR shell loop */ while(!ExitRequest) { /* Display the shell prompt */ PrintPrompt(); /* Read a command line */ ReadCommand(CommandLine, XTBL_SH_MAX_LINE_LENGTH); /* Parse the command line into a list of arguments */ Status = ParseCommand(CommandLine, &ArgumentCount, &ArgumentVector); if(Status != STATUS_EFI_SUCCESS) { /* Parsing failed, print error and continue */ Console::Print(L"ERROR: Failed to parse command line (Status: 0x%llx).\n\n", Status); continue; } /* Check if command line is empty */ if(ArgumentCount == 0) { /* Skip empty command line */ continue; } /* Check if command line starts with a comment symbol (#) */ if(ArgumentVector[0][0] != L'#') { /* Dispatch the command */ ExecuteCommand(ArgumentCount, ArgumentVector); } /* Free the argument vector */ Memory::FreePool(ArgumentVector); /* Print a trailing blank line for visual separation */ Console::Print(L"\n"); } } ================================================ FILE: boot/xtldr/textui.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/textui.cc * DESCRIPTION: Text console User Interface (TUI) support for XT Boot Loader * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Determines dialog box size based on enabled components and message length. * * @param Handle * Supplies a pointer to the dialog box handle. * * @param Message * Supplies a pointer to the message string put on the dialog box. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DetermineDialogBoxSize(IN OUT PXTBL_DIALOG_HANDLE Handle, IN PCWSTR Message) { UINT_PTR Width, Height, LineLength; SIZE_T Index, MessageLength; UCHAR Attributes; ULONG Mask; /* Set minimum dialog window size */ Height = 4; Width = 36; /* Zero line length */ LineLength = 0; /* Adjust window height according to enabled components */ Mask = 1; Attributes = Handle->Attributes; while(Mask) { /* Check enabled components that affect dialog window size */ switch(Attributes & Mask) { case XTBL_TUI_DIALOG_ACTIVE_BUTTON: case XTBL_TUI_DIALOG_INACTIVE_BUTTON: Height += 1; break; case XTBL_TUI_DIALOG_ACTIVE_INPUT: case XTBL_TUI_DIALOG_INACTIVE_INPUT: case XTBL_TUI_DIALOG_PROGRESS_BAR: Height += 2; break; } /* Update component attributes mask */ Attributes &= ~Mask; Mask <<= 1; } /* Check if input field is active */ if(Handle->Attributes & (XTBL_TUI_DIALOG_ACTIVE_INPUT | XTBL_TUI_DIALOG_INACTIVE_INPUT)) { /* Set maximum dialog window width to fit input field */ Width = XTBL_TUI_MAX_DIALOG_WIDTH; } /* Get message length and count dialog window dimensions */ MessageLength = RTL::WideString::WideStringLength(Message, 0); for(Index = 0; Index < MessageLength; Index++) { /* Check if this is multiline message */ if(Message[Index] == L'\n' || Index == MessageLength - 1) { /* Check if this line exceeds current dialog window width */ if(LineLength > Width) { /* Update dialog window width */ Width = LineLength; } /* Increase dialog window height to fit next line */ Height++; LineLength = 0; } else { /* Increase dialog window width to fit next character */ LineLength++; } } /* Add more space to dialog window to fit side borders */ Width += 4; /* Get console resolution */ Console::QueryMode(&Handle->ResX, &Handle->ResY); /* Make sure dialog window fits in the buffer */ if(Width > XTBL_TUI_MAX_DIALOG_WIDTH) { /* Set maximum dialog window width */ Width = XTBL_TUI_MAX_DIALOG_WIDTH; } /* Make sure dialog window fits on the screen (X axis) and it is not too small for input field */ if(Width > (Handle->ResX - 2)) { /* Set maximum dialog window width */ Width = Handle->ResX - 2; } /* Make sure dialog window fits on the screen (Y axis)*/ if(Height > (Handle->ResY - 2)) { /* Set maximum dialog window height */ Height = Handle->ResY - 2; } /* Set dialog window final dimensions */ Handle->PosX = (Handle->ResX - Width) / 2; Handle->PosY = (Handle->ResY - Height) / 2; Handle->Width = Width; Handle->Height = Height; } /** * Displays a simple TUI-based boot menu. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DisplayBootMenu() { XTBL_DIALOG_HANDLE Handle; PXTBL_BOOTMENU_ITEM MenuEntries = NULLPTR; ULONG Index; ULONG HighligtedEntryId, OldHighligtedEntryId, NumberOfEntries, TopVisibleEntry, VisibleEntries; BOOLEAN RedrawBootMenu, RedrawEntries; UINT_PTR EventIndex; EFI_EVENT Events[2]; EFI_INPUT_KEY Key; EFI_EVENT TimerEvent; EFI_STATUS Status; LONG TimeOut; PWCHAR TimeOutString; /* Draw boot menu */ DrawBootMenu(&Handle); /* Initialize boot menu list */ TopVisibleEntry = 0; Status = Configuration::InitializeBootMenuList(Handle.Width - 4, &MenuEntries, &NumberOfEntries, &HighligtedEntryId); if(Status != STATUS_EFI_SUCCESS) { /* Failed to initialize boot menu list, exit into XTLDR shell */ return; } /* Calculate how many entries can be visible in the menu box */ VisibleEntries = Handle.Height - 2; /* Adjust the view if the default entry is not initially visible */ if(HighligtedEntryId >= VisibleEntries) { /* Scroll the view to make the highlighted entry the last visible one */ TopVisibleEntry = HighligtedEntryId - VisibleEntries + 1; } /* Get timeout from the configuration */ Configuration::GetValue(L"TIMEOUT", &TimeOutString); TimeOut = -1; /* Check if timeout is specified */ if(TimeOutString != NULLPTR) { /* Convert timeout string to number */ TimeOut = 0; while(*TimeOutString >= '0' && *TimeOutString <= '9') { TimeOut *= 10; TimeOut += *TimeOutString - '0'; TimeOutString++; } } /* Set redraw flags to not redraw the menu itself, but fill it with entries */ RedrawBootMenu = FALSE; RedrawEntries = TRUE; /* Infinite boot menu loop */ while(TRUE) { /* Redraw boot menu frame if requested */ if(RedrawBootMenu) { DrawBootMenu(&Handle); RedrawBootMenu = FALSE; RedrawEntries = TRUE; } /* Sanity check to ensure we do not display more entries than possible */ if(VisibleEntries > NumberOfEntries) { VisibleEntries = NumberOfEntries; } /* Check if there is anything to show in the boot menu */ if(NumberOfEntries > 0) { /* Check if we need to redraw boot menu entries */ if(RedrawEntries) { /* Iterate through all menu entries */ for(Index = 0; Index < VisibleEntries; Index++) { /* Draw menu entry */ DrawBootMenuEntry(&Handle, MenuEntries[TopVisibleEntry + Index].EntryName, Index, (BOOLEAN)((TopVisibleEntry + Index) == HighligtedEntryId)); } /* Clear redraw entries flag */ RedrawEntries = FALSE; } } else { /* No menu entries found, show error message */ DisplayErrorDialog(L"XTLDR", L"No boot menu entries found in the configuration. Falling back to shell."); /* Exit into XTLDR shell */ return; } /* Create a timer event for controlling the timeout of the boot menu */ Status = XtLoader::GetEfiSystemTable()->BootServices->CreateEvent(EFI_EVENT_TIMER, EFI_TPL_CALLBACK, NULLPTR, NULLPTR, &TimerEvent); if(Status == STATUS_EFI_SUCCESS) { /* Setup new EFI timer */ Status = XtLoader::GetEfiSystemTable()->BootServices->SetTimer(TimerEvent, TimerPeriodic, 10000000); } /* Check is EFI timer was successfully created */ if(Status != STATUS_EFI_SUCCESS) { /* Timer creation failed, disable the timer */ TimeOut = -1; } /* Initialize EFI events */ Events[0] = XtLoader::GetEfiSystemTable()->ConIn->WaitForKey; Events[1] = TimerEvent; /* Flush keyboard buffer out of any keystrokes */ XtLoader::GetEfiSystemTable()->ConIn->Reset(XtLoader::GetEfiSystemTable()->ConIn, FALSE); /* Store old highlighted entry */ OldHighligtedEntryId = HighligtedEntryId; /* Infinite boot menu event loop */ while(TRUE) { /* Wait for EFI event */ EfiUtils::WaitForEfiEvent(2, Events, &EventIndex); /* Check which event was received */ if(EventIndex == 0) { /* Key pressed, check if timer is still active */ if(TimeOut != -1) { /* Disable the timer */ TimeOut = -1; /* Cancel timer event */ XtLoader::GetEfiSystemTable()->BootServices->SetTimer(TimerEvent, TimerCancel, 0); /* Remove the timer message */ Console::ClearLine(Handle.PosY + Handle.Height + 4); } /* Read key stroke */ Console::ReadKeyStroke(&Key); if(Key.ScanCode == 0x03 || Key.UnicodeChar == 0x0D) { /* ENTER or RightArrow key pressed, boot the highlighted OS */ Console::SetAttributes(Handle.DialogColor | Handle.TextColor); Console::ClearLine(Handle.PosY + Handle.Height + 4); Console::SetCursorPosition(4, Handle.PosY + Handle.Height + 4); Console::Print(L"Booting '%S' now...\n", MenuEntries[HighligtedEntryId].FullName); /* Boot the highlighted (chosen) OS */ Status = Protocol::InvokeBootProtocol(MenuEntries[HighligtedEntryId].ShortName, MenuEntries[HighligtedEntryId].Options); if(Status != STATUS_SUCCESS) { /* Failed to boot OS */ Debug::Print(L"ERROR: Failed to boot '%S' (Status Code: 0x%zX)\n", MenuEntries[HighligtedEntryId].FullName, Status); DisplayErrorDialog(L"XTLDR", L"Failed to startup the selected Operating System."); RedrawBootMenu = TRUE; } /* Break from boot menu event loop to redraw whole boot menu */ break; } else if(Key.ScanCode == 0x01) { /* UpArrow key pressed, go to previous entry if possible */ if(HighligtedEntryId > 0) { /* Highlight previous entry */ OldHighligtedEntryId = HighligtedEntryId; HighligtedEntryId--; /* Check if we need to scroll the view */ if(HighligtedEntryId < TopVisibleEntry) { /* Scroll the view */ TopVisibleEntry = HighligtedEntryId; RedrawEntries = TRUE; break; } /* Redraw new highlighted entry and the old one */ DrawBootMenuEntry(&Handle, MenuEntries[OldHighligtedEntryId].EntryName, OldHighligtedEntryId - TopVisibleEntry, (BOOLEAN)FALSE); DrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName, HighligtedEntryId - TopVisibleEntry, (BOOLEAN)TRUE); } } else if(Key.ScanCode == 0x02) { /* DownArrow key pressed, go to next entry if possible */ if(HighligtedEntryId < NumberOfEntries - 1) { /* Highlight next entry */ OldHighligtedEntryId = HighligtedEntryId; HighligtedEntryId++; /* Check if we need to scroll the view */ if(HighligtedEntryId >= TopVisibleEntry + VisibleEntries) { /* Scroll the view */ TopVisibleEntry = HighligtedEntryId - VisibleEntries + 1; RedrawEntries = TRUE; break; } /* Redraw new highlighted entry and the old one */ DrawBootMenuEntry(&Handle, MenuEntries[OldHighligtedEntryId].EntryName, OldHighligtedEntryId - TopVisibleEntry, (BOOLEAN)FALSE); DrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName, HighligtedEntryId - TopVisibleEntry, (BOOLEAN)TRUE); } } else if(Key.ScanCode == 0x09) { /* PageUp key pressed, go to top entry */ if(HighligtedEntryId != 0) { /* Highlight first entry */ HighligtedEntryId = 0; TopVisibleEntry = 0; RedrawEntries = TRUE; break; } } else if(Key.ScanCode == 0x0A) { /* PageDown key pressed, go to bottom entry */ if(HighligtedEntryId != NumberOfEntries - 1) { /* Highlight last entry */ HighligtedEntryId = NumberOfEntries - 1; TopVisibleEntry = (NumberOfEntries > VisibleEntries) ? (NumberOfEntries - VisibleEntries) : 0; RedrawEntries = TRUE; break; } } else if(Key.ScanCode == 0x0B) { /* F1 key pressed, show help */ DisplayInfoDialog(L"XTLDR", L"XTLDR, the XTOS Boot Loader for UEFI and EFI-based machines.\n" L" \n" L"Use arrow keys (Up/Down) to change the highlighted entry and\n" L"PgUp/PgDown keys to jump to the first/last position.\n" L" \n" L"Press ENTER key to boot the highlighted boot menu entry.\n" L"Press 'e' key to edit the highlighted menu entry.\n" L"Press 's' key to exit into XTLDR shell (enters advanced mode).\n" L" \n" L"F1 shows this help, F10 reboots into UEFI firmware interface,\n" L"F11 reboots the machine and F12 turns it off.\n" L" \n" L" \n" L"XTLDR is a part of the ExectOS Operating System.\n" L"Visit https://exectos.eu.org/ for more information."); /* Break from boot menu event loop to redraw whole boot menu */ RedrawBootMenu = TRUE; break; } else if(Key.ScanCode == 0x14) { /* F10 key pressed, reboot into UEFI setup interface */ EfiUtils::EnterFirmwareSetup(); DisplayErrorDialog(L"XTLDR", L"Reboot into firmware setup interface not supported!"); RedrawBootMenu = TRUE; /* Break from boot menu event loop to redraw whole boot menu */ break; } else if(Key.ScanCode == 0x15) { /* F11 key pressed, reboot the machine */ EfiUtils::RebootSystem(); DisplayErrorDialog(L"XTLDR", L"Failed to reboot the machine!"); RedrawBootMenu = TRUE; /* Break from boot menu event loop to redraw whole boot menu */ break; } else if(Key.ScanCode == 0x16) { /* F12 key pressed, shutdown the machine */ EfiUtils::ShutdownSystem(); DisplayErrorDialog(L"XTLDR", L"Failed to shutdown the machine!"); RedrawBootMenu = TRUE; /* Break from boot menu event loop to redraw whole boot menu */ break; } else if(Key.UnicodeChar == 0x65) { /* 'e' key pressed, edit the highlighted entry */ DisplayEditMenu(&MenuEntries[HighligtedEntryId]); RedrawBootMenu = TRUE; /* Break from boot menu event loop to redraw whole boot menu */ break; } else if(Key.UnicodeChar == 0x73) { /* 's' key pressed, exit into XTLDR shell */ return; } } else { /* Timer tick, check if time out expired */ if(TimeOut > 0) { /* Update a message and decrease timeout value */ Console::SetAttributes(Handle.DialogColor | Handle.TextColor); Console::ClearLine(Handle.PosY + Handle.Height + 4); Console::SetCursorPosition(4, Handle.PosY + Handle.Height + 4); Console::Print(L"The highlighted position will be booted automatically in %ld seconds.", TimeOut); TimeOut--; } else if(TimeOut == 0) { /* Time out expired, update a message */ Console::SetAttributes(Handle.DialogColor | Handle.TextColor); Console::ClearLine(Handle.PosY + Handle.Height + 4); Console::SetCursorPosition(4, Handle.PosY + Handle.Height + 4); Console::Print(L"Booting '%S' now...\n", MenuEntries[HighligtedEntryId].FullName); /* Disable the timer just in case booting OS fails */ TimeOut = -1; /* Boot the highlighted (default) OS */ Status = Protocol::InvokeBootProtocol(MenuEntries[HighligtedEntryId].ShortName, MenuEntries[HighligtedEntryId].Options); if(Status != STATUS_SUCCESS) { /* Failed to boot OS */ Debug::Print(L"ERROR: Failed to boot '%S' (Status Code: 0x%zX)\n", MenuEntries[HighligtedEntryId].FullName, Status); DisplayErrorDialog(L"XTLDR", L"Failed to startup the selected Operating System."); RedrawBootMenu = TRUE; } break; } } } } } /** * Displays a simple TUI-based edit menu. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DisplayEditMenu(IN PXTBL_BOOTMENU_ITEM MenuEntry) { ULONG HighligtedOptionId, Index, NumberOfOptions, OldHighligtedOptionId, TopVisibleEntry, VisibleEntries; XTBL_DIALOG_HANDLE Handle; BOOLEAN RedrawEditMenu, RedrawEntries; EFI_INPUT_KEY Key; UINT_PTR EventIndex; PWCHAR NewValue, OriginalValue, Value, ValueToEdit; PCWSTR OptionName, *EditableOptions; EFI_STATUS Status; /* Draw edit menu */ DrawEditMenu(&Handle); /* Get the list of user editable options */ Configuration::GetEditableOptions(&EditableOptions, &NumberOfOptions); /* Calculate how many entries can be visible in the menu box */ VisibleEntries = Handle.Height - 2; /* Assume the first option is highlighted by default */ HighligtedOptionId = 0; OldHighligtedOptionId = 0; TopVisibleEntry = 0; /* Set redraw flags to not redraw the menu itself, but fill it with entries */ RedrawEditMenu = FALSE; RedrawEntries = TRUE; /* Infinite edit menu loop */ while(TRUE) { /* Redraw edit menu frame if requested */ if(RedrawEditMenu) { DrawEditMenu(&Handle); RedrawEditMenu = FALSE; RedrawEntries = TRUE; } /* Sanity check to ensure we do not display more entries than possible */ if(VisibleEntries > NumberOfOptions) { VisibleEntries = NumberOfOptions; } /* Check if we need to redraw boot menu entries */ if(RedrawEntries) { /* Iterate through all menu entries */ for(Index = 0; Index < VisibleEntries; Index++) { /* Draw menu entry */ Configuration::GetBootOptionValue(MenuEntry->Options, EditableOptions[TopVisibleEntry + Index], &Value); DrawEditMenuEntry(&Handle, EditableOptions[TopVisibleEntry + Index], Value, Index, (BOOLEAN)((TopVisibleEntry + Index) == HighligtedOptionId)); /* Free allocated value string if needed */ if(Value != NULLPTR) { Memory::FreePool(Value); } } /* Clear redraw entries flag */ RedrawEntries = FALSE; } /* Wait for EFI event and read key stroke */ EfiUtils::WaitForEfiEvent(1, &(XtLoader::GetEfiSystemTable()->ConIn->WaitForKey), &EventIndex); Console::ReadKeyStroke(&Key); /* Check key press scan code */ if(Key.UnicodeChar == 0x0D || Key.UnicodeChar == 0x65) { /* ENTER or 'e' key pressed, edit the highlighted option */ OptionName = EditableOptions[HighligtedOptionId]; Configuration::GetBootOptionValue(MenuEntry->Options, OptionName, &OriginalValue); /* If the original value is NULLPTR, use an empty string for editing */ if(OriginalValue == NULLPTR) { ValueToEdit = (PWCHAR)L""; } else { ValueToEdit = OriginalValue; } /* Display input dialog to edit the option value */ NewValue = ValueToEdit; DisplayInputDialog(OptionName, L"Enter new value:", &NewValue); /* Check if the value was changed */ if(NewValue != ValueToEdit) { /* Update the boot option with the new value and free the old value */ Configuration::SetBootOptionValue(MenuEntry->Options, OptionName, NewValue); Memory::FreePool(NewValue); } /* Free the original value if it was allocated */ if(OriginalValue != NULLPTR) { Memory::FreePool(OriginalValue); } /* Mark the edit menu for redraw */ RedrawEditMenu = TRUE; } else if(Key.ScanCode == 0x01) { /* UpArrow key pressed, go to previous entry if possible */ if(HighligtedOptionId > 0) { /* Highlight previous entry */ OldHighligtedOptionId = HighligtedOptionId; HighligtedOptionId--; /* Check if we need to scroll the view */ if(HighligtedOptionId < TopVisibleEntry) { /* Scroll the view */ TopVisibleEntry = HighligtedOptionId; RedrawEntries = TRUE; continue; } /* Redraw old highlighted entry */ Configuration::GetBootOptionValue(MenuEntry->Options, EditableOptions[OldHighligtedOptionId], &Value); DrawEditMenuEntry(&Handle, EditableOptions[OldHighligtedOptionId], Value, OldHighligtedOptionId - TopVisibleEntry, (BOOLEAN)FALSE); /* Free allocated value string if needed */ if(Value != NULLPTR) { Memory::FreePool(Value); } /* Redraw new highlighted entry */ Configuration::GetBootOptionValue(MenuEntry->Options, EditableOptions[HighligtedOptionId], &Value); DrawEditMenuEntry(&Handle, EditableOptions[HighligtedOptionId], Value, HighligtedOptionId - TopVisibleEntry, (BOOLEAN)TRUE); /* Free allocated value string if needed */ if(Value != NULLPTR) { Memory::FreePool(Value); } } } else if(Key.ScanCode == 0x02) { /* DownArrow key pressed, go to next entry if possible */ if(HighligtedOptionId < NumberOfOptions - 1) { /* Highlight next entry */ OldHighligtedOptionId = HighligtedOptionId; HighligtedOptionId++; /* Check if we need to scroll the view */ if(HighligtedOptionId >= TopVisibleEntry + VisibleEntries) { /* Scroll the view */ TopVisibleEntry = HighligtedOptionId - VisibleEntries + 1; RedrawEntries = TRUE; continue; } /* Redraw old highlighted entry */ Configuration::GetBootOptionValue(MenuEntry->Options, EditableOptions[OldHighligtedOptionId], &Value); DrawEditMenuEntry(&Handle, EditableOptions[OldHighligtedOptionId], Value, OldHighligtedOptionId - TopVisibleEntry, (BOOLEAN)FALSE); /* Free allocated value string if needed */ if(Value != NULLPTR) { Memory::FreePool(Value); } /* Redraw new highlighted entry */ Configuration::GetBootOptionValue(MenuEntry->Options, EditableOptions[HighligtedOptionId], &Value); DrawEditMenuEntry(&Handle, EditableOptions[HighligtedOptionId], Value, HighligtedOptionId - TopVisibleEntry, (BOOLEAN)TRUE); /* Free allocated value string if needed */ if(Value != NULLPTR) { Memory::FreePool(Value); } } } else if(Key.ScanCode == 0x09) { /* PageUp key pressed, go to top entry */ if(HighligtedOptionId != 0) { /* Highlight first entry */ HighligtedOptionId = 0; TopVisibleEntry = 0; RedrawEntries = TRUE; } } else if(Key.ScanCode == 0x0A) { /* PageDown key pressed, go to bottom entry */ if(HighligtedOptionId != NumberOfOptions - 1) { /* Highlight last entry */ HighligtedOptionId = NumberOfOptions - 1; TopVisibleEntry = (NumberOfOptions > VisibleEntries) ? (NumberOfOptions - VisibleEntries) : 0; RedrawEntries = TRUE; } } else if(Key.ScanCode == 0x14) { /* F10 key pressed, boot the OS */ Console::SetAttributes(Handle.DialogColor | Handle.TextColor); Console::ClearLine(Handle.PosY + Handle.Height + 4); Console::SetCursorPosition(4, Handle.PosY + Handle.Height + 4); Console::Print(L"Booting '%S' now...\n", MenuEntry->FullName); /* Boot the OS */ Status = Protocol::InvokeBootProtocol(MenuEntry->ShortName, MenuEntry->Options); if(Status != STATUS_SUCCESS) { /* Failed to boot OS */ Debug::Print(L"ERROR: Failed to boot '%S' (Status Code: 0x%zX)\n", MenuEntry->FullName, Status); DisplayErrorDialog(L"XTLDR", L"Failed to startup the selected Operating System."); RedrawEditMenu = TRUE; } /* Return to the edit menu */ continue; } else if(Key.ScanCode == 0x17) { /* ESC key pressed, exit edit menu */ break; } } } /** * Displays a red error dialog box with the specified caption and message. * * @param Caption * Supplies a caption string put on the dialog box. * * @param Message * Supplies a message string put on the dialog box. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DisplayErrorDialog(IN PCWSTR Caption, IN PCWSTR Message) { XTBL_DIALOG_HANDLE Handle; EFI_INPUT_KEY Key; UINT_PTR Index; /* Set dialog window attributes */ Handle.Attributes = XTBL_TUI_DIALOG_ERROR_BOX | XTBL_TUI_DIALOG_ACTIVE_BUTTON; /* Determine dialog window size and position */ DetermineDialogBoxSize(&Handle, Message); /* Disable cursor and draw dialog box */ Console::DisableCursor(); DrawDialogBox(&Handle, Caption, Message); /* Draw active button */ DrawButton(&Handle); /* Initialize key stroke */ Key.ScanCode = 0; Key.UnicodeChar = 0; /* Wait until ENTER or ESC key is pressed */ while(Key.ScanCode != 0x17 && Key.UnicodeChar != 0x0D) { /* Wait for key press and read key stroke */ EfiUtils::WaitForEfiEvent(1, &(XtLoader::GetEfiSystemTable()->ConIn->WaitForKey), &Index); Console::ReadKeyStroke(&Key); Console::ResetInputBuffer(); } /* Clear screen to remove dialog box */ Console::SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); Console::ClearScreen(); } /** * Displays a blue informational dialog box with the specified caption and message. * * @param Caption * Supplies a caption string put on the dialog box. * * @param Message * Supplies a message string put on the dialog box. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DisplayInfoDialog(IN PCWSTR Caption, IN PCWSTR Message) { XTBL_DIALOG_HANDLE Handle; EFI_INPUT_KEY Key; UINT_PTR Index; /* Set dialog window attributes */ Handle.Attributes = XTBL_TUI_DIALOG_GENERIC_BOX | XTBL_TUI_DIALOG_ACTIVE_BUTTON; /* Determine dialog window size and position */ DetermineDialogBoxSize(&Handle, Message); /* Disable cursor and draw dialog box */ Console::DisableCursor(); DrawDialogBox(&Handle, Caption, Message); /* Draw active button */ DrawButton(&Handle); /* Initialize key stroke */ Key.ScanCode = 0; Key.UnicodeChar = 0; /* Wait until ENTER or ESC key is pressed */ while(Key.ScanCode != 0x17 && Key.UnicodeChar != 0x0D) { /* Wait for key press and read key stroke */ EfiUtils::WaitForEfiEvent(1, &(XtLoader::GetEfiSystemTable()->ConIn->WaitForKey), &Index); Console::ReadKeyStroke(&Key); Console::ResetInputBuffer(); } /* Clear screen to remove dialog box */ Console::SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); Console::ClearScreen(); } /** * Displays a blue informational dialog box with the specified caption and message and an input field. * * @param Caption * Specifies a caption string put on the dialog box. * * @param Message * Specifies a message string put on the dialog box. * * @param InputFieldText * Specifies a pointer to the input field text that will be edited. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DisplayInputDialog(IN PCWSTR Caption, IN PCWSTR Message, IN OUT PWCHAR *InputFieldText) { SIZE_T InputFieldLength, TextCursorPosition, TextIndex, TextPosition; XTBL_DIALOG_HANDLE Handle; PWCHAR InputFieldBuffer; EFI_INPUT_KEY Key; EFI_STATUS Status; UINT_PTR Index; /* Set dialog window attributes */ Handle.Attributes = XTBL_TUI_DIALOG_GENERIC_BOX | XTBL_TUI_DIALOG_ACTIVE_INPUT | XTBL_TUI_DIALOG_INACTIVE_BUTTON; /* Determine dialog window size and position */ DetermineDialogBoxSize(&Handle, Message); /* Disable cursor and draw dialog box */ Console::DisableCursor(); DrawDialogBox(&Handle, Caption, Message); /* Draw inactive button */ DrawButton(&Handle); /* Draw active input field */ DrawInputField(&Handle, *InputFieldText); /* Initialize key stroke */ Key.ScanCode = 0; Key.UnicodeChar = 0; /* Determine input field length */ InputFieldLength = RTL::WideString::WideStringLength(*InputFieldText, 0); /* Allocate a buffer for storing the input field text */ Status = Memory::AllocatePool(2048 * sizeof(WCHAR), (PVOID *)&InputFieldBuffer); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, print error message and return */ Debug::Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status); DisplayErrorDialog(L"XTLDR", L"Failed to allocate memory for input field buffer."); return; } /* Copy input text into edit buffer */ RTL::Memory::CopyMemory(InputFieldBuffer, *InputFieldText, InputFieldLength * sizeof(WCHAR)); InputFieldBuffer[InputFieldLength] = L'\0'; /* Start at first character */ TextPosition = 0; Console::SetCursorPosition(Handle.PosX + 4 + TextPosition, Handle.PosY + Handle.Height - 4); /* Wait until ENTER or ESC key is pressed */ while(TRUE) { /* Wait for key press and read key stroke */ EfiUtils::WaitForEfiEvent(1, &(XtLoader::GetEfiSystemTable()->ConIn->WaitForKey), &Index); Console::ReadKeyStroke(&Key); /* Check key press scan code */ if(Key.ScanCode == 0x17) { /* ESC key pressed, return */ break; } else if(Key.UnicodeChar == 0x09) { /* TAB key pressed, toggle input field and button */ Handle.Attributes ^= (XTBL_TUI_DIALOG_ACTIVE_INPUT | XTBL_TUI_DIALOG_INACTIVE_INPUT); Handle.Attributes ^= (XTBL_TUI_DIALOG_ACTIVE_BUTTON | XTBL_TUI_DIALOG_INACTIVE_BUTTON); } else if(Key.ScanCode == 0x03) { /* RIGHT key pressed, move cursor forward */ if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && TextPosition < InputFieldLength) { TextPosition++; } } else if(Key.ScanCode == 0x04) { /* LEFT key pressed, move cursor back */ if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && TextPosition > 0) { TextPosition--; } } else if(Key.ScanCode == 0x05) { /* HOME key pressed, move cursor to the beginning */ if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) { TextPosition = 0; } } else if(Key.ScanCode == 0x06) { /* END key pressed, move cursor to the end */ if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) { TextPosition = InputFieldLength; } } else if(Key.ScanCode == 0x08) { /* DELETE key pressed, delete character */ if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) { /* Check if buffer is not empty */ if(InputFieldLength > 0 && TextPosition < InputFieldLength) { /* Delete character */ RTL::Memory::MoveMemory(InputFieldBuffer + TextPosition, InputFieldBuffer + TextPosition + 1, (InputFieldLength - TextPosition) * sizeof(WCHAR)); /* Decrement length and NULL terminate string */ InputFieldLength--; InputFieldBuffer[InputFieldLength] = L'\0'; } } } else if(Key.UnicodeChar == 0x08) { /* BACKSPACE key pressed, delete character */ if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) { /* Check if buffer is not empty */ if(InputFieldLength > 0 && TextPosition > 0 && TextPosition <= InputFieldLength) { /* Move memory to overwrite the character to the left of the cursor */ RTL::Memory::MoveMemory(InputFieldBuffer + TextPosition - 1, InputFieldBuffer + TextPosition, (InputFieldLength - TextPosition + 1) * sizeof(WCHAR)); /* Decrement length, position and NULL terminate string */ TextPosition--; InputFieldLength--; InputFieldBuffer[InputFieldLength] = L'\0'; } } } else if(Key.UnicodeChar == 0x0D) { /* ENTER key pressed, update input buffer */ *InputFieldText = InputFieldBuffer; break; } else { /* Other key pressed, add character to the buffer */ if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && Key.UnicodeChar != 0) { /* Check if buffer is full */ if(InputFieldLength < 2047) { /* Insert character at current position */ RTL::Memory::MoveMemory(InputFieldBuffer + TextPosition + 1, InputFieldBuffer + TextPosition, (InputFieldLength - TextPosition) * sizeof(WCHAR)); InputFieldBuffer[TextPosition] = Key.UnicodeChar; /* Increment length, position and NULL terminate string */ TextPosition++; InputFieldLength++; InputFieldBuffer[InputFieldLength] = L'\0'; } } } /* Calculate text index and cursor position */ if(TextPosition > (Handle.Width - 9)) { TextIndex = TextPosition - (Handle.Width - 9); TextCursorPosition = Handle.Width - 9; } else { TextIndex = 0; TextCursorPosition = TextPosition; } /* Redraw input field and button */ DrawButton(&Handle); DrawInputField(&Handle, &InputFieldBuffer[TextIndex]); /* Set cursor position if input field is active */ if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) { Console::SetCursorPosition(Handle.PosX + 4 + TextCursorPosition, Handle.PosY + Handle.Height - 4); } } /* Clear screen to remove dialog box */ Console::SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); Console::ClearScreen(); } /** * Displays a blue informational dialog box with the specified caption and message and a progress bar. * * @param Caption * Supplies a caption string put on the dialog box. * * @param Message * Supplies a message string put on the dialog box. * * @param Percentage * Specifies the percentage progress of the progress bar. * * @return This routine returns a dialog box handle needed to update the progress bar. * * @since XT 1.0 */ XTCDECL XTBL_DIALOG_HANDLE TextUi::DisplayProgressDialog(IN PCWSTR Caption, IN PCWSTR Message, IN UCHAR Percentage) { XTBL_DIALOG_HANDLE Handle; /* Set dialog window attributes */ Handle.Attributes = XTBL_TUI_DIALOG_GENERIC_BOX | XTBL_TUI_DIALOG_PROGRESS_BAR; /* Determine dialog window size and position */ DetermineDialogBoxSize(&Handle, Message); /* Disable cursor and draw dialog box */ Console::DisableCursor(); DrawDialogBox(&Handle, Caption, Message); /* Draw active button */ DrawProgressBar(&Handle, Percentage); /* Return dialog handle */ return Handle; } /** * Draws a text UI-based boot menu. * * @param Handle * Supplies a pointer to the boot menu handle. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DrawBootMenu(OUT PXTBL_DIALOG_HANDLE Handle) { /* Query console screen resolution */ Console::QueryMode(&Handle->ResX, &Handle->ResY); /* Set boot menu parameters */ Handle->Attributes = 0; Handle->DialogColor = EFI_TEXT_BGCOLOR_BLACK; Handle->TextColor = EFI_TEXT_FGCOLOR_LIGHTGRAY; Handle->PosX = 3; Handle->PosY = 3; Handle->Width = Handle->ResX - 6; Handle->Height = Handle->ResY - 10; /* Clear screen and disable cursor */ Console::SetAttributes(Handle->DialogColor | Handle->TextColor); Console::ClearScreen(); Console::DisableCursor(); /* Check if debugging enabled */ if(DEBUG) { /* Print debug version of XTLDR banner */ Console::SetCursorPosition((Handle->ResX - 44) / 2, 1); Console::Print(L"XTLDR Boot Loader v%d.%d (%s-%s)\n", XTLDR_VERSION_MAJOR, XTLDR_VERSION_MINOR, XTOS_VERSION_DATE, XTOS_VERSION_HASH); } else { /* Print standard XTLDR banner */ Console::SetCursorPosition((Handle->ResX - 22) / 2, 1); Console::Print(L"XTLDR Boot Loader v%d.%d\n", XTLDR_VERSION_MAJOR, XTLDR_VERSION_MINOR); } /* Draw empty dialog box for boot menu */ DrawDialogBox(Handle, NULLPTR, NULLPTR); /* Print help message below the boot menu */ Console::SetCursorPosition(0, Handle->PosY + Handle->Height); Console::SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); Console::Print(L" Use cursors to change the selection. Press ENTER key to boot the chosen\n" L" Operating System, 'e' to edit it before booting or 's' for XTLDR shell.\n" L" Additional help available after pressing F1 key."); } /** * Draws boot menu entry at the specified position. * * @param Handle * Supplies a pointer to the boot menu handle. * * @param MenuEntry * Supplies a pointer to the buffer containing a menu entry name. * * @param Position * Specifies entry position on the list in the boot menu. * * @param Highlighted * Specifies whether this entry should be highlighted or not. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DrawBootMenuEntry(IN PXTBL_DIALOG_HANDLE Handle, IN PWCHAR MenuEntry, IN UINT Position, IN BOOLEAN Highlighted) { UINT Index; /* Move cursor to the right position */ Console::SetCursorPosition(5, 4 + Position); /* Check whether this entry should be highlighted */ if(Highlighted) { /* Highlight this entry */ Console::SetAttributes(EFI_TEXT_BGCOLOR_LIGHTGRAY | EFI_TEXT_FGCOLOR_BLACK); } else { /* Set default colors */ Console::SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); } /* Clear menu entry */ for(Index = 0; Index < Handle->Width - 4; Index++) { Console::Print(L" "); } /* Print menu entry */ Console::SetCursorPosition(5, 4 + Position); Console::Print(L"%S\n", MenuEntry); } /** * Draws dialog box with caption and message. * * @param Handle * Supplies a pointer to the dialog box handle. * * @param Caption * Specifies a caption string put on the dialog box. * * @param Message * Specifies a message string put on the dialog box. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DrawDialogBox(IN OUT PXTBL_DIALOG_HANDLE Handle, IN PCWSTR Caption, IN PCWSTR Message) { WCHAR BoxLine[XTBL_TUI_MAX_DIALOG_WIDTH]; SIZE_T CaptionLength; UINT_PTR PosX, PosY; /* Set dialog colors */ if(Handle->Attributes & XTBL_TUI_DIALOG_ERROR_BOX) { /* Error dialog with red background and brown button */ Handle->DialogColor = EFI_TEXT_BGCOLOR_RED; Handle->TextColor = EFI_TEXT_FGCOLOR_WHITE; } else if(Handle->Attributes & XTBL_TUI_DIALOG_GENERIC_BOX) { /* Generic dialog with blue background and cyan button */ Handle->DialogColor = EFI_TEXT_BGCOLOR_BLUE; Handle->TextColor = EFI_TEXT_FGCOLOR_WHITE; } /* Set dialog box colors */ Console::SetAttributes(Handle->DialogColor | 0x0F); /* Iterate through dialog box lines */ for(PosY = Handle->PosY; PosY < Handle->PosY + Handle->Height; PosY++) { /* Set cursor position in the appropriate place */ Console::SetCursorPosition(Handle->PosX, PosY); /* Draw dialog box */ if(PosY == Handle->PosY) { /* Draw top line of the dialog box, starting from the left corner */ BoxLine[0] = EFI_TEXT_BOX_DOWN_RIGHT; /* Check if there is a caption for this dialog */ if(Caption != NULLPTR) { /* Get caption length */ CaptionLength = RTL::WideString::WideStringLength(Caption, 0); /* Start caption area with vertical line */ BoxLine[1] = EFI_TEXT_BOX_VERTICAL_LEFT; /* Fill caption area with spaces */ for(PosX = 2; PosX < CaptionLength + 4; PosX++) { BoxLine[PosX] = ' '; } /* End caption area with vertical line */ BoxLine[CaptionLength + 4] = EFI_TEXT_BOX_VERTICAL_RIGHT; } else { /* No caption, -4 because of left and right vertical lines and corresponding spaces */ CaptionLength = -4; } /* Draw bottom line */ for(PosX = CaptionLength + 5; PosX < Handle->Width - 1; PosX++) { BoxLine[PosX] = EFI_TEXT_BOX_HORIZONTAL; } /* End with top right corner */ BoxLine[Handle->Width - 1] = EFI_TEXT_BOX_DOWN_LEFT; } else if(PosY == Handle->PosY + Handle->Height - 1) { /* Draw bottom line of the dialog box, starting from the left corner */ BoxLine[0] = EFI_TEXT_BOX_UP_LEFT; /* Fill bottom with horizontal line */ for(PosX = 1; PosX < Handle->Width - 1; PosX++) { BoxLine[PosX] = EFI_TEXT_BOX_HORIZONTAL; } /* End with bottom right corner */ BoxLine[Handle->Width - 1] = EFI_TEXT_BOX_UP_RIGHT; } else { /* Draw the middle of the dialog box */ BoxLine[0] = EFI_TEXT_BOX_VERTICAL; /* Fill dialog box with spaces */ for(PosX = 1; PosX < Handle->Width - 1; PosX++) { BoxLine[PosX] = ' '; } /* End with vertical line */ BoxLine[Handle->Width - 1] = EFI_TEXT_BOX_VERTICAL; } /* Add NULL terminator to the end of the line */ BoxLine[Handle->Width] = 0; /* Write the line to the console */ Console::Write(BoxLine); } /* Make sure there is a caption to print */ if(Caption != NULLPTR) { /* Write dialog box caption */ Console::SetCursorPosition(Handle->PosX + 3, Handle->PosY); Console::Print(L"%S", Caption); } /* Make sure there is a message to print */ if(Message != NULLPTR) { /* Write a message on the dialog box */ DrawMessage(Handle, Message); } } /** * Draws an active or inactive button in the dialog box, depending on the attributes. * * @param Handle * Supplies a pointer to the dialog box handle. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DrawButton(IN PXTBL_DIALOG_HANDLE Handle) { ULONG ButtonColor, TextColor; /* Set dialog button colors */ if(Handle->Attributes & XTBL_TUI_DIALOG_ACTIVE_BUTTON) { /* This is an active button */ if(Handle->Attributes & XTBL_TUI_DIALOG_ERROR_BOX) { /* This is an error dialog box */ ButtonColor = EFI_TEXT_BGCOLOR_BROWN; TextColor = EFI_TEXT_FGCOLOR_WHITE; } else { /* This is a generic dialog box */ ButtonColor = EFI_TEXT_BGCOLOR_CYAN; TextColor = EFI_TEXT_FGCOLOR_WHITE; } } else { /* This is an inactive button */ ButtonColor = EFI_TEXT_BGCOLOR_LIGHTGRAY; TextColor = EFI_TEXT_FGCOLOR_BLACK; } /* Disable cursor and draw dialog button */ Console::DisableCursor(); Console::SetAttributes(ButtonColor | TextColor); Console::SetCursorPosition(Handle->ResX / 2 - 4, Handle->PosY + Handle->Height - 2); Console::Print(L"[ OK ]"); } /** * Draws an active or inactive input field in the dialog box, depending on the attributes. * * @param Handle * Supplies a pointer to the dialog box handle. * * @param InputFieldText * Supplies a pointer to the wide char string that will be displayed in the input field. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DrawInputField(IN PXTBL_DIALOG_HANDLE Handle, IN PWCHAR InputFieldText) { WCHAR InputField[XTBL_TUI_MAX_DIALOG_WIDTH]; ULONG InputColor, TextColor; UINT_PTR Index, Position; SIZE_T Length; /* Set dialog button colors */ if(Handle->Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) { /* This is an active input field */ if(Handle->Attributes & XTBL_TUI_DIALOG_ERROR_BOX) { /* This is an error dialog box */ InputColor = EFI_TEXT_BGCOLOR_BROWN; TextColor = EFI_TEXT_FGCOLOR_WHITE; } else { /* This is a generic dialog box */ InputColor = EFI_TEXT_BGCOLOR_CYAN; TextColor = EFI_TEXT_FGCOLOR_WHITE; } } else { /* This is an inactive input field */ InputColor = EFI_TEXT_BGCOLOR_LIGHTGRAY; TextColor = EFI_TEXT_FGCOLOR_BLACK; } /* Set progress bar color and position */ Console::SetAttributes(InputColor | TextColor); Position = (Handle->Attributes & (XTBL_TUI_DIALOG_ACTIVE_BUTTON | XTBL_TUI_DIALOG_INACTIVE_BUTTON)) ? 4 : 3; Console::SetCursorPosition(Handle->PosX + 4, Handle->PosY + Handle->Height - Position); /* Draw input field */ for(Index = 0; Index < Handle->Width - 8; Index++) { /* Fill input field with spaces */ InputField[Index] = L' '; } /* Disable cursor and write input field to console */ Console::DisableCursor(); Console::Write(InputField); /* Check input field text length */ Length = RTL::WideString::WideStringLength(InputFieldText, 0); if(Length > (Handle->Width - 9)) { /* Text longer than input field width, display only part of it */ Length = Handle->Width - 9; } /* Copy a part of input field text to input field */ for(Index = 0; Index < Length; Index++) { /* Write input field text */ InputField[Index] = InputFieldText[Index]; } /* Add NULL terminator to the end of the line */ InputField[Handle->Width] = 0; /* Write input field text */ Console::SetCursorPosition(Handle->PosX + 4, Handle->PosY + Handle->Height - Position); Console::Write(InputField); /* Check if this is an active input field */ if(Handle->Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) { /* Enable cursor for active input field */ Console::EnableCursor(); } } /** * Draws a message on the dialog box specified by the handle. * * @param Handle * Supplies a pointer to the dialog box handle. * * @param Message * Supplies a message that will be displayed on the dialog box. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DrawMessage(IN PXTBL_DIALOG_HANDLE Handle, IN PCWSTR Message) { PWCHAR Msg, MsgLine, LastMsgLine; SIZE_T Index, Length, LineLength; EFI_STATUS Status; ULONG Line; /* Allocate memory for dialog box message */ Length = RTL::WideString::WideStringLength(Message, 0); Status = Memory::AllocatePool(Length * sizeof(WCHAR), (PVOID *)&Msg); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, print debug message and return */ Debug::Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status); return; } /* Make a copy of dialog box message */ RTL::Memory::CopyMemory(Msg, Message, Length * sizeof(WCHAR)); Msg[Length] = 0; /* Tokenize dialog box message */ MsgLine = RTL::WideString::TokenizeWideString(Msg, L"\n", &LastMsgLine); /* Iterate through message lines */ Line = 0; while(MsgLine) { /* Determine line length */ LineLength = RTL::WideString::WideStringLength(MsgLine, 0); /* Write line in the dialog box */ Console::SetCursorPosition(Handle->PosX + 2, Handle->PosY + 2 + Line); Console::SetAttributes(Handle->DialogColor | Handle->TextColor); Console::Print(L"%S", MsgLine); /* Check if message line is shorter than the dialog box working area */ if(LineLength < Handle->Width - 4) { /* Fill the rest of the line with spaces */ for(Index = LineLength; Index < Handle->Width - 4; Index++) { Console::Print(L" "); } } /* Get next line */ MsgLine = RTL::WideString::TokenizeWideString(NULLPTR, L"\n", &LastMsgLine); Line++; } } /** * Draws a progress bar component in the dialog box. * * @param Handle * Supplies a pointer to the dialog box handle. * * @param Percentage * Specifies the percentage progress of the progress bar. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DrawProgressBar(IN PXTBL_DIALOG_HANDLE Handle, IN UCHAR Percentage) { UINT_PTR Index, ProgressLength, ProgressBarLength; WCHAR ProgressBar[XTBL_TUI_MAX_DIALOG_WIDTH]; UINT_PTR Position; /* Determine progress bar length and calculate progress */ ProgressBarLength = Handle->Width - 8; ProgressLength = (ProgressBarLength * Percentage) / 100; /* Set progress bar color and position */ Console::SetAttributes(EFI_TEXT_FGCOLOR_YELLOW); Position = (Handle->Attributes & (XTBL_TUI_DIALOG_ACTIVE_BUTTON | XTBL_TUI_DIALOG_INACTIVE_BUTTON)) ? 4 : 3; Console::SetCursorPosition(Handle->PosX + 4, Handle->PosY + Handle->Height - Position); /* Draw progress bar */ for(Index = 0; Index < ProgressBarLength; Index++) { /* Fill progress bar */ if(Index < ProgressLength) { /* Fill with full block */ ProgressBar[Index] = EFI_TEXT_BOX_FULL_BLOCK; } else { /* Fill with light block */ ProgressBar[Index] = EFI_TEXT_BOX_LIGHT_BLOCK; } } /* Terminate progress bar string */ ProgressBar[Index] = 0; /* Disable cursor and write progress bar to console */ Console::DisableCursor(); Console::Write(ProgressBar); } /** * Draws a text-based boot edition menu. * * @param Handle * Supplies a pointer to the edition menu handle. * * @return This function does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::DrawEditMenu(OUT PXTBL_DIALOG_HANDLE Handle) { /* Query console screen resolution */ Console::QueryMode(&Handle->ResX, &Handle->ResY); /* Set boot menu parameters */ Handle->Attributes = 0; Handle->DialogColor = EFI_TEXT_BGCOLOR_BLACK; Handle->TextColor = EFI_TEXT_FGCOLOR_LIGHTGRAY; Handle->PosX = 3; Handle->PosY = 3; Handle->Width = Handle->ResX - 6; Handle->Height = Handle->ResY - 10; /* Clear screen and disable cursor */ Console::SetAttributes(Handle->DialogColor | Handle->TextColor); Console::ClearScreen(); Console::DisableCursor(); /* Check if debugging enabled */ if(DEBUG) { /* Print debug version of XTLDR banner */ Console::SetCursorPosition((Handle->ResX - 44) / 2, 1); Console::Print(L"XTLDR Boot Loader v%d.%d (%s-%s)\n", XTLDR_VERSION_MAJOR, XTLDR_VERSION_MINOR, XTOS_VERSION_DATE, XTOS_VERSION_HASH); } else { /* Print standard XTLDR banner */ Console::SetCursorPosition((Handle->ResX - 22) / 2, 1); Console::Print(L"XTLDR Boot Loader v%d.%d\n", XTLDR_VERSION_MAJOR, XTLDR_VERSION_MINOR); } /* Draw empty dialog box for boot menu */ DrawDialogBox(Handle, L"Edit Options", NULLPTR); /* Print help message below the edit menu */ Console::SetCursorPosition(0, Handle->PosY + Handle->Height); Console::SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); Console::Print(L" Use cursors to change the selection. Press ENTER key to edit the chosen\n" L" option, ESC to return to the main boot menu or F10 to boot.\n"); } /** * Draws edit menu entry at the specified position. * * @param Handle * Supplies a pointer to the boot menu handle. * * @param OptionName * Supplies a pointer to the buffer containing a part of the menu entry name (an option name). * * @param OptionValue * Supplies a pointer to the buffer containing a part of the menu entry name (an option value). * * @param Position * Specifies entry position on the list in the boot menu. * * @param Highlighted * Specifies whether this entry should be highlighted or not. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL EFI_STATUS TextUi::DrawEditMenuEntry(IN PXTBL_DIALOG_HANDLE Handle, IN PCWSTR OptionName, IN PCWSTR OptionValue, IN UINT Position, IN BOOLEAN Highlighted) { BOOLEAN Allocation; PCWSTR DisplayValue, ShortValue; UINT Index; ULONG OptionNameLength, OptionValueLength, OptionWidth; EFI_STATUS Status; /* Assume no allocation was made */ Allocation = FALSE; /* Set display value depending on input */ DisplayValue = (OptionValue != NULLPTR) ? OptionValue : L""; /* Determine lengths */ OptionNameLength = RTL::WideString::WideStringLength(OptionName, 0); OptionValueLength = RTL::WideString::WideStringLength(DisplayValue, 0); OptionWidth = Handle->Width - 4 - (OptionNameLength + 2); /* Check if value needs to be truncated */ if(OptionValueLength > OptionWidth) { /* Allocate buffer for new, shortened value */ Status = Memory::AllocatePool((OptionWidth + 1) * sizeof(WCHAR), (PVOID *)&ShortValue); // This allocates PWCHAR if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure, print debug message and return */ Debug::Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status); return Status; } /* Copy a desired value length into the allocated buffer and append "..." */ RTL::Memory::CopyMemory((PWCHAR)ShortValue, DisplayValue, (OptionWidth - 3) * sizeof(WCHAR)); RTL::Memory::CopyMemory((PWCHAR)ShortValue + OptionWidth - 3, L"...", 3 * sizeof(WCHAR)); ((PWCHAR)ShortValue)[OptionWidth] = L'\0'; /* Mark that allocation was made and set new display value */ Allocation = TRUE; DisplayValue = ShortValue; } /* Move cursor to the right position */ Console::SetCursorPosition(5, 4 + Position); /* Check whether this entry should be highlighted */ if(Highlighted) { /* Highlight this entry */ Console::SetAttributes(EFI_TEXT_BGCOLOR_LIGHTGRAY | EFI_TEXT_FGCOLOR_BLACK); } else { /* Set default colors */ Console::SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); } /* Clear menu entry */ for(Index = 0; Index < Handle->Width - 4; Index++) { Console::Print(L" "); } /* Print menu entry */ Console::SetCursorPosition(5, 4 + Position); Console::Print(L"%S: %S", OptionName, DisplayValue); /* Check if allocation was made */ if(Allocation) { /* Free allocated memory */ Memory::FreePool((PVOID)DisplayValue); } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Updates the progress bar on the dialog box. * * @param Handle * Supplies a pointer to the dialog box handle. * * @param Message * Supplies a new message that will be put on the dialog box, while updating the progress bar. * * @param Percentage * Specifies the new percentage progress of the progress bar. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID TextUi::UpdateProgressBar(IN PXTBL_DIALOG_HANDLE Handle, IN PCWSTR Message, IN UCHAR Percentage) { /* Check if message needs an update */ if(Message != NULLPTR) { /* Update a message on the dialog box */ DrawMessage(Handle, Message); } /* Update progress bar */ DrawProgressBar(Handle, Percentage); } ================================================ FILE: boot/xtldr/volume.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/volume.cc * DESCRIPTION: XTLDR volume support * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * This routine closes an EFI volume handle. * * @param VolumeHandle * Specifies a handle of opened volume. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Volume::CloseVolume(IN PEFI_HANDLE VolumeHandle) { EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; /* Make sure a handle specified */ if(VolumeHandle != NULLPTR) { /* Close a handle */ return XtLoader::GetEfiSystemTable()->BootServices->CloseProtocol(VolumeHandle, &LIPGuid, XtLoader::GetEfiImageHandle(), NULLPTR); } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Discovers and enumerates a block devices available to EFI system. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Volume::EnumerateBlockDevices() { EFI_GUID LoadedImageProtocolGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; EFI_GUID BlockIoGuid = EFI_BLOCK_IO_PROTOCOL_GUID; EFI_HANDLE BootDeviceHandle = NULLPTR, DeviceHandle = NULLPTR; EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; PEFI_DEVICE_PATH_PROTOCOL DevicePath = NULLPTR, LastNode = NULLPTR; PEFI_BLOCK_DEVICE_DATA ParentNode = NULLPTR; PEFI_BLOCK_DEVICE_DATA BlockDeviceData; PEFI_BLOCK_DEVICE BlockDevice; LIST_ENTRY BlockDevices; PLIST_ENTRY ListEntry; EFI_STATUS Status; PEFI_ACPI_HID_DEVICE_PATH AcpiDevice; PEFI_HARDDRIVE_DEVICE_PATH HDPath; PEFI_BLOCK_IO_MEDIA Media; PEFI_GUID PartitionGuid; ULONG DriveNumber, PartitionNumber; USHORT DriveType; ULONG CDCount = 0, FDCount = 0, HDCount = 0, RDCount = 0; /* Get the device handle of the image that is running */ Status = XtLoader::GetEfiSystemTable()->BootServices->HandleProtocol(XtLoader::GetEfiImageHandle(), &LoadedImageProtocolGuid, (VOID**)&LoadedImage); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get boot device handle */ Debug::Print(L"ERROR: Failed to get boot device handle (Status Code: 0x%zX)\n", Status); return Status; } /* Save the boot device handle */ BootDeviceHandle = LoadedImage->DeviceHandle; /* Initialize list entries */ RTL::LinkedList::InitializeListHead(&BlockDevices); RTL::LinkedList::InitializeListHead(&EfiBlockDevices); /* Discover EFI block devices and store them in linked list */ Status = DiscoverEfiBlockDevices(&BlockDevices); if(Status != STATUS_EFI_SUCCESS) { Debug::Print(L"ERROR: Failed to discover EFI block devices (Status Code: 0x%zX)\n", Status); return Status; } /* Identify all discovered devices */ ListEntry = BlockDevices.Flink; while(ListEntry != &BlockDevices) { /* Get data for the next discovered device. */ BlockDeviceData = CONTAIN_RECORD(ListEntry, EFI_BLOCK_DEVICE_DATA, ListEntry); PartitionGuid = NULLPTR; /* Find last node */ Status = FindLastBlockDeviceNode(BlockDeviceData->DevicePath, &LastNode); if(Status != STATUS_EFI_SUCCESS) { /* Skip this device if its last node cannot be found, as it is required for classification */ Debug::Print(L"WARNING: Block device last node not found\n"); ListEntry = ListEntry->Flink; continue; } /* Initialize drive type before attempting to classify the device */ DriveType = XTBL_BOOT_DEVICE_UNKNOWN; /* Locate the parent for this block device to ensure it is not an orphaned entry */ if(!FindParentBlockDevice(&BlockDevices, BlockDeviceData, &ParentNode)) { /* Orphaned device found. Log a warning and skip it as it cannot be properly classified */ Debug::Print(L"WARNING: No parent device found, skipping orphaned media device path\n"); ListEntry = ListEntry->Flink; continue; } /* Verify that media information is available, as some devices may not report it */ if(!BlockDeviceData->BlockIo->Media) { /* The device is unusable without media info, log a warning and skip it */ Debug::Print(L"WARNING: Block device is missing media information\n"); ListEntry = ListEntry->Flink; continue; } Media = BlockDeviceData->BlockIo->Media; /* Check last node type */ if(LastNode->Type == EFI_ACPI_DEVICE_PATH && LastNode->SubType == EFI_ACPI_DP) { /* Check for Floppy EISA identifiers */ AcpiDevice = (PEFI_ACPI_HID_DEVICE_PATH)LastNode; if(AcpiDevice->HID == 0x60441D0 || AcpiDevice->HID == 0x70041D0 || AcpiDevice->HID == 0x70141D1) { /* Floppy drive found */ DriveType = XTBL_BOOT_DEVICE_FLOPPY; DriveNumber = FDCount++; PartitionNumber = 0; /* Print debug message */ Debug::Print(L"Found Floppy Disk (DiskNumber: %lu, MediaPresent: %u, RO: %u)\n", DriveNumber, Media->MediaPresent, Media->ReadOnly); } } else if((LastNode->Type == EFI_MEDIA_DEVICE_PATH && LastNode->SubType == EFI_MEDIA_CDROM_DP) || (LastNode->Type == EFI_MESSAGING_DEVICE_PATH && (LastNode->SubType == EFI_MESSAGING_ATAPI_DP || LastNode->SubType == EFI_MESSAGING_SATA_DP) && Media->MediaPresent && Media->RemovableMedia)) { /* Optical drive found */ DriveType = XTBL_BOOT_DEVICE_CDROM; DriveNumber = CDCount++; PartitionNumber = 0; /* Print debug message */ Debug::Print(L"Found CD-ROM drive (DriveNumber: %lu, MediaPresent: %u, RemovableMedia: %u, RO: %u)\n", DriveNumber, Media->MediaPresent, Media->RemovableMedia, Media->ReadOnly); } else if(LastNode->Type == EFI_MEDIA_DEVICE_PATH && LastNode->SubType == EFI_MEDIA_HARDDRIVE_DP) { /* Hard disk partition found */ HDPath = (PEFI_HARDDRIVE_DEVICE_PATH)LastNode; DriveType = XTBL_BOOT_DEVICE_HARDDISK; DriveNumber = (HDPath->PartitionNumber == 1) ? HDCount++ : HDCount - 1; PartitionNumber = HDPath->PartitionNumber; PartitionGuid = (PEFI_GUID)HDPath->Signature; /* Check if this is the EFI System Partition (ESP) */ if(BootDeviceHandle != NULLPTR) { /* Allocate memory for device path */ DevicePath = DuplicateDevicePath(BlockDeviceData->DevicePath); if(DevicePath != NULLPTR) { /* Check if this is the boot device */ Status = XtLoader::GetEfiSystemTable()->BootServices->LocateDevicePath(&BlockIoGuid, &DevicePath, &DeviceHandle); if(Status == STATUS_EFI_SUCCESS && DeviceHandle == BootDeviceHandle) { /* Mark partition as ESP */ DriveType |= XTBL_BOOT_DEVICE_ESP; } } } /* Print debug message */ Debug::Print(L"Found Hard Disk partition (DiskNumber: %lu, PartNumber: %lu, " L"MBRType: %u, GUID: {%V}, PartSize: %lluB) %S\n", DriveNumber, PartitionNumber, HDPath->MBRType, PartitionGuid, HDPath->PartitionSize * Media->BlockSize, (DriveType & XTBL_BOOT_DEVICE_ESP) ? L"(ESP)" : L""); } else if(LastNode->Type == EFI_MEDIA_DEVICE_PATH && LastNode->SubType == EFI_MEDIA_RAMDISK_DP) { /* RAM disk found */ DriveType = XTBL_BOOT_DEVICE_RAMDISK; DriveNumber = RDCount++; PartitionNumber = 0; /* Print debug message */ Debug::Print(L"Found RAM Disk (DiskNumber: %lu, MediaPresent: %u)\n", DriveNumber, Media->MediaPresent); } /* Make sure the device found has valid type set */ if(DriveType != XTBL_BOOT_DEVICE_UNKNOWN) { /* Allocate memory for block device */ Status = Memory::AllocatePool(sizeof(EFI_BLOCK_DEVICE), (PVOID *)&BlockDevice); if(Status != STATUS_EFI_SUCCESS) { Debug::Print(L"ERROR: Failed to allocate memory pool for block device (Status Code: 0x%zX)\n", Status); return STATUS_EFI_OUT_OF_RESOURCES; } /* Initialize block device */ BlockDevice->DevicePath = DuplicateDevicePath(BlockDeviceData->DevicePath); BlockDevice->DriveType = DriveType; BlockDevice->DriveNumber = DriveNumber; BlockDevice->PartitionNumber = PartitionNumber; BlockDevice->PartitionGuid = PartitionGuid; /* Add block device to global list */ RTL::LinkedList::InsertTailList(&EfiBlockDevices, &BlockDevice->ListEntry); } /* Get next entry from linked list */ ListEntry = ListEntry->Flink; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Finds an EFI device path for a specified path on a given file system. * * @param FsHandle * The handle of the corresponding file system. * * @param FileSystemPath * Specifies a path on the corresponding file system. * * @param DevicePath * Specifies a pointer to the memory area, where found device path will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Volume::FindDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL FsHandle, IN CONST PWCHAR FileSystemPath, OUT PEFI_DEVICE_PATH_PROTOCOL* DevicePath) { EFI_STATUS Status; SIZE_T FsPathLength, DevicePathLength = 0; PEFI_FILEPATH_DEVICE_PATH FilePath = NULLPTR; PEFI_DEVICE_PATH_PROTOCOL EndDevicePath; PEFI_DEVICE_PATH_PROTOCOL DevicePathHandle; /* Set local device path handle */ DevicePathHandle = FsHandle; /* Find the end device path node */ while(TRUE) { /* Make sure there is a next node */ if(*(PUSHORT)DevicePathHandle->Length == 0) { /* End device path not found */ return STATUS_EFI_NOT_FOUND; } /* Check if end device path node found */ if(DevicePathHandle->Type == EFI_END_DEVICE_PATH) { /* End device path node found */ break; } /* Get next node */ DevicePathLength += *(PUSHORT)DevicePathHandle->Length; DevicePathHandle = (PEFI_DEVICE_PATH_PROTOCOL)((PUCHAR)DevicePathHandle + *(PUSHORT)DevicePathHandle->Length); } /* Check real path length */ FsPathLength = RTL::WideString::WideStringLength(FileSystemPath, 0) * sizeof(WCHAR); /* Allocate memory pool for device path */ Status = Memory::AllocatePool(FsPathLength + DevicePathLength + sizeof(EFI_DEVICE_PATH_PROTOCOL), (PVOID *)DevicePath); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Set file path */ RTL::Memory::CopyMemory(*DevicePath, FsHandle, DevicePathLength); FilePath = (PEFI_FILEPATH_DEVICE_PATH)((PUCHAR)*DevicePath + DevicePathLength); FilePath->Header.Type = EFI_MEDIA_DEVICE_PATH; FilePath->Header.SubType = EFI_MEDIA_FILEPATH_DP; FilePath->Header.Length[0] = (UCHAR)FsPathLength + FIELD_OFFSET(EFI_FILEPATH_DEVICE_PATH, PathName) + sizeof(WCHAR); FilePath->Header.Length[1] = FilePath->Header.Length[0] >> 8; /* Set device path end node */ RTL::Memory::CopyMemory(FilePath->PathName, FileSystemPath, FsPathLength + sizeof(WCHAR)); EndDevicePath = (PEFI_DEVICE_PATH_PROTOCOL)&FilePath->PathName[(FsPathLength / sizeof(WCHAR)) + 1]; EndDevicePath->Type = EFI_END_DEVICE_PATH; EndDevicePath->SubType = EFI_END_ENTIRE_DP; EndDevicePath->Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL); EndDevicePath->Length[1] = 0; /* Return success */ return STATUS_EFI_SUCCESS; } /** * Creates a copy of the system path with EFI standard directory separators. * * @param SystemPath * Supplies a pointer to the system path. * * @param EfiPath * Supplies a pointer to the memory area, where EFI path will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Volume::GetEfiPath(IN PWCHAR SystemPath, OUT PWCHAR *EfiPath) { SIZE_T Index, PathLength; EFI_STATUS Status; /* Get system path length */ PathLength = RTL::WideString::WideStringLength(SystemPath, 0); /* Allocate memory for storing EFI path */ Status = Memory::AllocatePool(sizeof(WCHAR) * (PathLength + 1), (PVOID *)EfiPath); if(Status != STATUS_EFI_SUCCESS) { /* Failed to allocate memory, print error message and return status code */ Debug::Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status); return STATUS_EFI_OUT_OF_RESOURCES; } /* Make a copy of SystemPath string */ RTL::Memory::CopyMemory(*EfiPath, SystemPath, sizeof(WCHAR) * (PathLength + 1)); /* Replace directory separator if needed to comply with EFI standard */ for(Index = 0; Index < PathLength; Index++) { if((*EfiPath)[Index] == L'/') { /* Replace '/' with '\' */ (*EfiPath)[Index] = L'\\'; } } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Finds a volume device path based on the specified ARC name or UUID. * * @param SystemPath * An input string containing ARC/UUID path. * * @param DevicePath * Supplies a pointer to memory region where device path will be stored. * * @param Path * Supplies a pointer to the memory area, where path on device will be saved. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Volume::GetDevicePath(IN PWCHAR SystemPath, OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT PWCHAR *ArcName, OUT PWCHAR *Path) { PEFI_BLOCK_DEVICE Device; USHORT DriveType; ULONG DriveNumber; ULONG PartNumber; PWCHAR Volume; ULONG PathLength; PLIST_ENTRY ListEntry; EFI_STATUS Status; /* Make sure this is not set */ *DevicePath = NULLPTR; /* Find volume path and its length */ Volume = SystemPath; while(*Volume != '/' && *Volume != '\\' && *Volume != '\0') { Volume++; } PathLength = Volume - SystemPath; /* Check if valume path specified */ if(PathLength == 0) { /* No volume path available */ *Path = SystemPath; return STATUS_EFI_NOT_FOUND; } /* Check system path format */ if(SystemPath[0] == '{') { if(PathLength == GUID_STRING_LENGTH) { /* This is EFI GUID */ Debug::Print(L"WARNING: EFI/GPT GUID in system path is not supported\n"); return STATUS_EFI_UNSUPPORTED; } else if(PathLength == PARTUUID_STRING_LENGTH) { /* This is MBR UUID */ Debug::Print(L"WARNING: MBR partition UUID in system path is not supported\n"); return STATUS_EFI_UNSUPPORTED; } else { /* Invalid UUID format */ return STATUS_EFI_INVALID_PARAMETER; } } else { /* Defaults to ARC path, dissect it */ Status = DissectArcPath(SystemPath, ArcName, Path, &DriveType, &DriveNumber, &PartNumber); } /* Check if volume path parsed successfully */ if(Status != STATUS_EFI_SUCCESS) { /* Failed to parse system path */ Debug::Print(L"ERROR: Failed to parse system path: '%s' (Status Code: 0x%zX)\n", SystemPath, Status); return Status; } /* Look for block device corresponding to dissected ARC path */ ListEntry = EfiBlockDevices.Flink; while(ListEntry != &EfiBlockDevices) { /* Check if this is the volume we are looking for */ Device = CONTAIN_RECORD(ListEntry, EFI_BLOCK_DEVICE, ListEntry); if(DriveType == XTBL_BOOT_DEVICE_ESP) { /* ESP requested, verify if flag is set for this device */ if((Device->DriveType & XTBL_BOOT_DEVICE_ESP) != 0) { /* Found volume */ *DevicePath = Device->DevicePath; break; } } else { if(((Device->DriveType & DriveType) == DriveType) && (Device->DriveNumber == DriveNumber) && (Device->PartitionNumber == PartNumber)) { /* Found volume */ *DevicePath = Device->DevicePath; break; } } ListEntry = ListEntry->Flink; } /* Check if volume was found */ if(*DevicePath == NULLPTR) { /* Volume not found */ Debug::Print(L"ERROR: Volume (DriveType: %u, DriveNumber: %lu, PartNumber: %lu) not found\n", DriveType, DriveNumber, PartNumber); return STATUS_EFI_NOT_FOUND; } /* return success */ return STATUS_EFI_SUCCESS; } /** * This routine opens an EFI volume and corresponding filesystem. * * @param DevicePath * Specifies a device path of the volume to open. If not specifies, uses image protocol by default. * * @param DiskHandle * The handle of the opened disk volume. * * @param FsHandle * The handle of the opened file system. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Volume::OpenVolume(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_HANDLE DiskHandle, OUT PEFI_FILE_HANDLE *FsHandle) { EFI_GUID SFSGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; PEFI_SIMPLE_FILE_SYSTEM_PROTOCOL FileSystemProtocol; PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol; EFI_STATUS Status; /* Check if device path has been passed or not */ if(DevicePath != NULLPTR) { /* Locate the device path */ Status = XtLoader::GetEfiSystemTable()->BootServices->LocateDevicePath(&SFSGuid, &DevicePath, DiskHandle); if(Status != STATUS_EFI_SUCCESS) { /* Failed to locate device path */ return Status; } } else { /* Open the image protocol if no device path specified */ Status = XtLoader::GetEfiSystemTable()->BootServices->OpenProtocol(XtLoader::GetEfiImageHandle(), &LIPGuid, (PVOID *)&ImageProtocol, XtLoader::GetEfiImageHandle(), NULLPTR, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open image protocol */ return Status; } /* Store disk handle */ *DiskHandle = ImageProtocol->DeviceHandle; } /* Open the filesystem protocol */ Status = XtLoader::GetEfiSystemTable()->BootServices->OpenProtocol(*DiskHandle, &SFSGuid, (PVOID *)&FileSystemProtocol, XtLoader::GetEfiImageHandle(), NULLPTR, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); /* Check if filesystem protocol opened successfully */ if(Status != STATUS_EFI_SUCCESS) { /* Failed to open the filesystem protocol, close volume */ CloseVolume(DiskHandle); return Status; } /* Open the corresponding filesystem */ Status = FileSystemProtocol->OpenVolume(FileSystemProtocol, FsHandle); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open the filesystem, close volume */ CloseVolume(DiskHandle); return Status; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * Reads data from the file. * * @param DirHandle * Supplies a handle of the opened filesystem directory. * * @param FileName * Supplies the name of the file to read. * * @param FileData * Provides a buffer to store the data read from the file. * * @param FileSize * Provides a pointer to the variable to store a size of the buffer. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Volume::ReadFile(IN PEFI_FILE_HANDLE DirHandle, IN PCWSTR FileName, OUT PVOID *FileData, OUT PSIZE_T FileSize) { EFI_GUID FileInfoGuid = EFI_FILE_INFO_PROTOCOL_GUID; EFI_PHYSICAL_ADDRESS Address; PEFI_FILE_HANDLE FileHandle; PEFI_FILE_INFO FileInfo; EFI_STATUS Status; UINT_PTR ReadSize; SIZE_T Pages; Status = DirHandle->Open(DirHandle, &FileHandle, (PWCHAR)FileName, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open file */ return Status; } /* Set required size for getting file information */ ReadSize = sizeof(EFI_FILE_INFO) + 32; /* Allocate necessary amount of memory */ Status = Memory::AllocatePool(ReadSize, (PVOID *)&FileInfo); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ FileHandle->Close(FileHandle); return Status; } /* First attempt to get file information */ FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo); if(Status == STATUS_EFI_BUFFER_TOO_SMALL) { /* Buffer is too small, but EFI tells the required size, so reallocate */ Memory::FreePool(&FileInfo); Status = Memory::AllocatePool(ReadSize, (PVOID *)&FileInfo); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ FileHandle->Close(FileHandle); return Status; } /* Second attempt to get file information */ Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo); } /* Check if file information got successfully */ if(Status != STATUS_EFI_SUCCESS) { /* Unable to get file information */ FileHandle->Close(FileHandle); Memory::FreePool(&FileInfo); return Status; } /* Store file size and calculate number of pages */ *FileSize = FileInfo->FileSize; Pages = EFI_SIZE_TO_PAGES(FileInfo->FileSize); /* Allocate pages */ Status = Memory::AllocatePages(AllocateAnyPages, Pages, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Pages allocation failure */ FileHandle->Close(FileHandle); Memory::FreePool(&FileInfo); return Status; } /* Calculate number of bytes to read and zero memory */ ReadSize = Pages * EFI_PAGE_SIZE; *FileData = (PCHAR)(UINT_PTR)Address; RTL::Memory::ZeroMemory(*FileData, ReadSize); /* Read data from the file */ Status = FileHandle->Read(FileHandle, &ReadSize, *FileData); if(Status != STATUS_EFI_SUCCESS) { /* Failed to read data */ FileHandle->Close(FileHandle); Memory::FreePool(&FileInfo); Memory::FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)*FileData); return Status; } /* Close handle and free memory */ FileHandle->Close(FileHandle); Memory::FreePool(FileInfo); /* Return success */ return STATUS_EFI_SUCCESS; } /** * Gets a list of block devices from an EFI enabled BIOS. * * @param BlockDevices * Supplies a pointer to a variable to receive a list of EFI block devices. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Volume::DiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices) { EFI_GUID DevicePathGuid = EFI_DEVICE_PATH_PROTOCOL_GUID; EFI_GUID IoGuid = EFI_BLOCK_IO_PROTOCOL_GUID; PEFI_DEVICE_PATH_PROTOCOL DevicePath; PEFI_BLOCK_DEVICE_DATA BlockDevice; UINT_PTR HandlesCount, Index; PEFI_HANDLE Handles = NULLPTR; PEFI_BLOCK_IO_PROTOCOL Io; EFI_STATUS Status; /* Locate handles which support the disk I/O interface */ Status = Protocol::LocateProtocolHandles(&Handles, &HandlesCount, &IoGuid); if(Status != STATUS_EFI_SUCCESS) { /* Failed to locate handles */ Debug::Print(L"ERROR: Failed to locate block devices handles (Status Code: 0x%zX)\n", Status); return Status; } /* Iterate through all handles */ for(Index = 0; Index < HandlesCount; Index++) { /* Print debug message */ Debug::Print(L"Opening %lu block device from %lu discovered\n", Index + 1, HandlesCount); /* Open I/O protocol for given handle */ Io = NULLPTR; Status = Protocol::OpenProtocolHandle(Handles[Index], (PVOID *)&Io, &IoGuid); if(Status != STATUS_EFI_SUCCESS || Io == NULLPTR) { /* Failed to open I/O protocol, skip it */ Debug::Print(L"WARNING: Failed to open EFI Block I/O protocol (Status Code: 0x%zX)\n", Status); continue; } /* Check if this is iPXE stub */ if(Io->Media && Io->Media->BlockSize == 1 && Io->Media->MediaId == 0x69505845U) { /* Skip stub as it is non-functional */ Debug::Print(L"WARNING: Skipping iPXE stub block I/O protocol"); continue; } /* Check if DevicePath protocol is supported by this handle */ DevicePath = NULLPTR; Status = XtLoader::GetEfiSystemTable()->BootServices->HandleProtocol(Handles[Index], &DevicePathGuid, (PVOID *)&DevicePath); if(Status != STATUS_EFI_SUCCESS || DevicePath == NULLPTR) { /* Device failed to handle DP protocol */ Debug::Print(L"WARNING: Unable to open DevicePath protocol (Status Code: 0x%zX)\n", Status); XtLoader::GetEfiSystemTable()->BootServices->CloseProtocol(Handles[Index], &IoGuid, XtLoader::GetEfiImageHandle(), NULLPTR); continue; } /* Allocate memory for block device */ Status = Memory::AllocatePool(sizeof(*BlockDevice), (PVOID *)&BlockDevice); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ Debug::Print(L"ERROR: Failed to allocate memory pool for block device (Status Code: 0x%zX)\n", Status); XtLoader::GetEfiSystemTable()->BootServices->CloseProtocol(Handles[Index], &DevicePathGuid, XtLoader::GetEfiImageHandle(), NULLPTR); XtLoader::GetEfiSystemTable()->BootServices->CloseProtocol(Handles[Index], &IoGuid, XtLoader::GetEfiImageHandle(), NULLPTR); return Status; } /* Store new block device into a linked list */ BlockDevice->BlockIo = Io; BlockDevice->DevicePath = DevicePath; RTL::LinkedList::InsertTailList(BlockDevices, &BlockDevice->ListEntry); } /* Free handles buffer */ Memory::FreePool(Handles); /* Return success */ return STATUS_EFI_SUCCESS; } /** * Dissects a specified ARC name and provides detailed information about corresponding device and on disk path. * * @param SystemPath * Supplies an input ARC path. * * @param Path * Specifies a pointer to variable, where on disk path will be saved. * * @param DriveType * Supplies a pointer to the variable that receives a drive type. * * @param DriveNumber * Supplies a pointer to the variable that receives a drive number. * * @param PartNumber * Supplies a pointer to the variable that receives a parition number if applicable, otherwise stores 0 (zero). * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Volume::DissectArcPath(IN PWCHAR SystemPath, OUT PWCHAR *ArcName, OUT PWCHAR *Path, OUT PUSHORT DriveType, OUT PULONG DriveNumber, OUT PULONG PartNumber) { PWCHAR ArcPath, LocalArcName; ULONG ArcLength = 0; /* Set default values */ *DriveType = XTBL_BOOT_DEVICE_UNKNOWN; *DriveNumber = 0; *PartNumber = 0; /* Look for the ARC path */ if(RTL::WideString::CompareWideStringInsensitive(SystemPath, L"ramdisk(0)", 0) == 0) { /* This is RAM disk */ ArcLength = 10; *DriveType = XTBL_BOOT_DEVICE_RAMDISK; } else if(RTL::WideString::CompareWideStringInsensitive(SystemPath, L"multi(0)esp(0)", 0) == 0) { /* This is ESP */ ArcLength = 14; *DriveType = XTBL_BOOT_DEVICE_ESP; } else if(RTL::WideString::CompareWideStringInsensitive(SystemPath, L"multi(0)disk(0)", 0) == 0) { /* This is a multi-disk port */ ArcLength = 15; ArcPath = SystemPath + ArcLength; /* Check for disk type */ if(RTL::WideString::CompareWideStringInsensitive(ArcPath, L"cdrom(", 0) == 0) { /* This is an optical drive */ ArcLength += 6; /* Find drive number */ while(SystemPath[ArcLength] != ')' && SystemPath[ArcLength] != '\0') { if(SystemPath[ArcLength] >= '0' && SystemPath[ArcLength] <= '9') { /* Calculate drive number */ *DriveNumber *= 10; *DriveNumber += SystemPath[ArcLength] - '0'; } ArcLength++; } /* Set proper drive type */ *DriveType = XTBL_BOOT_DEVICE_CDROM; ArcLength++; } else if(RTL::WideString::CompareWideStringInsensitive(ArcPath, L"fdisk(", 0) == 0) { /* This is a floppy drive */ ArcLength += 6; /* Find drive number */ while(SystemPath[ArcLength] != ')' && SystemPath[ArcLength] != '\0') { if(SystemPath[ArcLength] >= '0' && SystemPath[ArcLength] <= '9') { /* Calculate drive number */ *DriveNumber *= 10; *DriveNumber += SystemPath[ArcLength] - '0'; } ArcLength++; } /* Set proper drive type */ *DriveType = XTBL_BOOT_DEVICE_FLOPPY; ArcLength++; } else if(RTL::WideString::CompareWideStringInsensitive(ArcPath, L"rdisk(", 0) == 0) { /* This is a hard disk */ ArcLength += 6; /* Find drive number */ while(SystemPath[ArcLength] != ')' && SystemPath[ArcLength] != '\0') { if(SystemPath[ArcLength] >= '0' && SystemPath[ArcLength] <= '9') { /* Calculate drive number */ *DriveNumber *= 10; *DriveNumber += SystemPath[ArcLength] - '0'; } ArcLength++; } /* Set proper drive type */ *DriveType = XTBL_BOOT_DEVICE_HARDDISK; ArcLength++; ArcPath = SystemPath + ArcLength; /* Look for a partition */ if(RTL::WideString::CompareWideStringInsensitive(ArcPath, L"partition(", 0) == 0) { /* Partition information found */ ArcLength += 10; /* Find partition number */ while(SystemPath[ArcLength] != ')' && SystemPath[ArcLength] != '\0') { if(SystemPath[ArcLength] >= '0' && SystemPath[ArcLength] <= '9') { /* Calculate partition number */ *PartNumber *= 10; *PartNumber += SystemPath[ArcLength] - '0'; } ArcLength++; } ArcLength++; } } else { /* Unsupported disk type */ return STATUS_EFI_UNSUPPORTED; } } else { /* Unsupported ARC path */ return STATUS_EFI_UNSUPPORTED; } /* Store the path if possible */ if(Path) { *Path = SystemPath + ArcLength; } /* Store ARC name if possible */ if(ArcName) { Memory::AllocatePool(ArcLength * sizeof(WCHAR), (PVOID *)&LocalArcName); RTL::Memory::CopyMemory(LocalArcName, SystemPath, ArcLength * sizeof(WCHAR)); LocalArcName[ArcLength] = '\0'; *ArcName = LocalArcName; } /* Return success */ return STATUS_EFI_SUCCESS; } /** * This routine duplicates a device path object. * * @param DevicePath * An input device path that is going to be clonned. * * @return Returns a duplicate of input device path. * * @since XT 1.0 */ XTCDECL PEFI_DEVICE_PATH_PROTOCOL Volume::DuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath) { PEFI_DEVICE_PATH_PROTOCOL DevicePathNode; PEFI_DEVICE_PATH_PROTOCOL DevicePathClone; EFI_STATUS Status; UINT Length = 0; /* Check if the input device path is NULL pointer */ if(!DevicePath) { /* Nothing to duplicate */ return NULLPTR; } /* Start iterating from the beginning of the device path */ DevicePathNode = DevicePath; /* Get the device path length */ while(TRUE) { Length += *(PUSHORT)DevicePathNode->Length; if(DevicePathNode->Type == EFI_END_DEVICE_PATH) { break; } DevicePathNode = (PEFI_DEVICE_PATH_PROTOCOL)((PUCHAR)DevicePathNode + *(PUSHORT)DevicePathNode->Length); } /* Check length */ if(Length == 0) { /* Nothing to duplicate */ return NULLPTR; } /* Allocate memory for the new device path */ Status = Memory::AllocatePool(Length, (PVOID *)&DevicePathClone); if(Status != STATUS_EFI_SUCCESS) { /* Failed to allocate memory */ Debug::Print(L"ERROR: Failed to allocate memory pool for device path duplicate (Status Code: 0x%zX)\n", Status); return NULLPTR; } /* Copy the device path */ RTL::Memory::CopyMemory(DevicePathClone, DevicePath, Length); /* Return the cloned object */ return DevicePathClone; } /** * Attempts to find a last node of the EFI block device. * * @param DevicePath * An input device path. * * @param LastNode * A pointer to the buffer where last node will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS Volume::FindLastBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_DEVICE_PATH_PROTOCOL *LastNode) { PEFI_DEVICE_PATH_PROTOCOL EndNode, NextNode; /* Make sure end is not reached yet */ if(DevicePath->Type == EFI_END_DEVICE_PATH) { /* End reached, nothing to do */ LastNode = NULLPTR; return STATUS_EFI_INVALID_PARAMETER; } /* Fast forward to the last node */ EndNode = DevicePath; while(EndNode->Type != EFI_END_DEVICE_PATH) { NextNode = EndNode; EndNode = (PEFI_DEVICE_PATH_PROTOCOL)((PUCHAR)EndNode + *(PUSHORT)EndNode->Length); } /* Store last node found */ *LastNode = NextNode; /* Return success */ return STATUS_EFI_SUCCESS; } /** * This routine attempts to find a parent device of the provided block device. * * @param BlockDevice * A linked list of discovered block devices. * * @param ChildNode * Block device that is looking for a parent device. * * @param ParentNode * A pointer to memory region where pointer to the parent node will be provided. * * @return This routine returns TRUE if parent node has been found, or FALSE otherwise. * * @since XT 1.0 */ XTCDECL BOOLEAN Volume::FindParentBlockDevice(IN PLIST_ENTRY BlockDevices, IN PEFI_BLOCK_DEVICE_DATA ChildNode, OUT PEFI_BLOCK_DEVICE_DATA *ParentNode) { PEFI_DEVICE_PATH_PROTOCOL ChildDevicePath, ParentDevicePath; PEFI_BLOCK_DEVICE_DATA BlockDeviceData; UINT ChildLength, ParentLength; PLIST_ENTRY ListEntry; ListEntry = BlockDevices->Flink; while(ListEntry != BlockDevices) { /* Take block device from the list */ BlockDeviceData = CONTAIN_RECORD(ListEntry, EFI_BLOCK_DEVICE_DATA, ListEntry); /* A device cannot be its own parent */ if (BlockDeviceData == ChildNode) { /* Move to the next device */ ListEntry = ListEntry->Flink; continue; } ChildDevicePath = ChildNode->DevicePath; ParentDevicePath = BlockDeviceData->DevicePath; /* Iterate nodes */ while(TRUE) { /* Check if the parent device is a match */ if(ParentDevicePath->Type == EFI_END_DEVICE_PATH) { /* Parent device is a match */ *ParentNode = BlockDeviceData; return TRUE; } /* Get child and parent node lengths */ ChildLength = *(PUSHORT)ChildDevicePath->Length; ParentLength = *(PUSHORT)ParentDevicePath->Length; /* Check if nodes match */ if((ChildLength != ParentLength) || (RTL::Memory::CompareMemory(ChildDevicePath, ParentDevicePath, ParentLength) != ParentLength)) { /* Nodes do not match, this is not a valid parent */ break; } /* Move to the next child and parent nodes */ ChildDevicePath = (PEFI_DEVICE_PATH_PROTOCOL)((PUCHAR)ChildDevicePath + ChildLength); ParentDevicePath = (PEFI_DEVICE_PATH_PROTOCOL)((PUCHAR)ParentDevicePath + ParentLength); } /* Get next entry from linked list */ ListEntry = ListEntry->Flink; } /* Apparently not found a parent node */ return FALSE; } ================================================ FILE: boot/xtldr/xtldr.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/xtldr.cc * DESCRIPTION: XTOS UEFI Boot Loader * DEVELOPERS: Rafal Kupiec */ #include /** * Disables access to EFI Boot Services. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID XtLoader::DisableBootServices() { LoaderStatus.BootServices = FALSE; } /** * Queries the availability of EFI Boot Services. * * @return This routine returns TRUE if EFI Boot Services are available, FALSE otherwise. * * @since XT 1.0 */ XTCDECL BOOLEAN XtLoader::GetBootServicesStatus() { return LoaderStatus.BootServices; } /** * Retrieves the EFI image handle. * * @return This routine returns a handle to the EFI-loaded image. * * @since XT 1.0 */ XTCDECL EFI_HANDLE XtLoader::GetEfiImageHandle() { return XtLoader::EfiImageHandle; } /** * Retrieves the EFI system table pointer. * * @return This routine returns a pointer to the EFI system table. * * @since XT 1.0 */ XTCDECL PEFI_SYSTEM_TABLE XtLoader::GetEfiSystemTable() { return XtLoader::EfiSystemTable; } /** * Provides base address and size of the XTLDR image. * * @param LoaderBase * Supplies a pointer to a variable that receives the base address of the XTLDR image. * * @param LoaderSize * Supplies a pointer to a variable that receives the size of the XTLDR image. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID XtLoader::GetLoaderImageInformation(PVOID *LoaderBase, PULONGLONG LoaderSize) { *LoaderBase = XtLoader::LoaderStatus.LoaderBase; *LoaderSize = XtLoader::LoaderStatus.LoaderSize; } /** * Retrieves the Secure Boot status. * * @return This routine returns SecureBoot status. * * @since XT 1.0 */ XTCDECL INT_PTR XtLoader::GetSecureBootStatus() { return LoaderStatus.SecureBoot; } /** * Initializes EFI Boot Loader (XTLDR). * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID XtLoader::InitializeBootLoader(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { EFI_GUID LipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; PEFI_LOADED_IMAGE_PROTOCOL LoadedImage; EFI_HANDLE Handle; EFI_STATUS Status; /* Set the system table and image handle */ EfiImageHandle = ImageHandle; EfiSystemTable = SystemTable; /* Set current XTLDR's EFI BootServices status */ LoaderStatus.BootServices = TRUE; /* Initialize console */ Console::InitializeConsole(); /* Print XTLDR version */ Console::Print(L"XTLDR boot loader v%s\n", XTOS_VERSION); /* Initialize XTLDR protocol */ Protocol::InitializeProtocol(); /* Initialize XTLDR configuration */ Configuration::InitializeConfiguration(); /* Store SecureBoot status */ LoaderStatus.SecureBoot = EfiUtils::GetSecureBootStatus(); /* Attempt to open EFI LoadedImage protocol */ Status = Protocol::OpenProtocol(&Handle, (PVOID *)&LoadedImage, &LipGuid); if(Status == STATUS_EFI_SUCCESS) { /* Store boot loader image base and size */ LoaderStatus.LoaderBase = LoadedImage->ImageBase; LoaderStatus.LoaderSize = LoadedImage->ImageSize; /* Check if debug is enabled */ if(DEBUG) { /* Protocol opened successfully, print useful debug information */ Console::Print(L"\n---------- BOOTLOADER DEBUG ----------\n" L"Pointer Size : %d\n" L"Image Base Address : %P\n" L"Image Base Size : 0x%lX\n" L"Image Revision : 0x%lX\n" L"Secure Boot Status : %zd\n" L"--------------------------------------\n", sizeof(PVOID), LoadedImage->ImageBase, LoadedImage->ImageSize, LoadedImage->Revision, LoaderStatus.SecureBoot); EfiUtils::SleepExecution(3000); } /* Close EFI LoadedImage protocol */ Protocol::CloseProtocol(&Handle, &LipGuid); } } /** * Registers a boot menu callback routine, that will be used to display alternative boot menu. * * @param BootMenuRoutine * Supplies a pointer to the boot menu callback routine. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID XtLoader::RegisterBootMenu(IN PVOID BootMenuRoutine) { /* Set boot menu routine */ BootMenu = (PBL_XT_BOOT_MENU)BootMenuRoutine; } /** * Invokes either a custom boot menu handler, if one has been registered, or displays the default boot menu. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID XtLoader::ShowBootMenu() { /* Check if custom boot menu registered */ if(BootMenu != NULLPTR) { /* Display alternative boot menu */ BootMenu(); } else { /* Display default boot menu */ TextUi::DisplayBootMenu(); } } /** * This routine is the entry point of the XT EFI boot loader. * * @param ImageHandle * Firmware-allocated handle that identifies the image. * * @param SystemTable * Provides the EFI system table. * * @return This routine returns status code. * * @since XT 1.0 */ XTCDECL EFI_STATUS BlStartXtLoader(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { PWCHAR Modules; EFI_STATUS Status; /* Check if system is EFI-based and provided parameters are valid */ if(ImageHandle == NULLPTR || SystemTable == NULLPTR) { /* Invalid parameters, print error message using BIOS calls and hang */ BiosUtils::ClearScreen(); BiosUtils::Print(L"XTLDR requires EFI-based system!"); for(;;); } /* Initialize XTLDR and */ XtLoader::InitializeBootLoader(ImageHandle, SystemTable); /* Parse configuration options passed from UEFI shell */ Status = Configuration::ParseCommandLine(); if(Status != STATUS_EFI_SUCCESS) { /* Failed to parse command line options */ TextUi::DisplayErrorDialog(L"XTLDR", L"Failed to parse command line parameters."); } /* Attempt to early initialize debug console */ if(DEBUG) { Status = Debug::InitializeDebugConsole(); if(Status != STATUS_EFI_SUCCESS) { /* Initialization failed, notify user on stdout */ TextUi::DisplayErrorDialog(L"XTLDR", L"Failed to initialize debug console."); } } /* Load XTLDR configuration file */ Status = Configuration::LoadConfiguration(); if(Status != STATUS_EFI_SUCCESS) { /* Failed to load/parse config file */ TextUi::DisplayErrorDialog(L"XTLDR", L"Failed to load and parse configuration file "); } /* Reinitialize debug console if it was not initialized earlier */ if(DEBUG) { Status = Debug::InitializeDebugConsole(); if(Status != STATUS_EFI_SUCCESS) { /* Initialization failed, notify user on stdout */ TextUi::DisplayErrorDialog(L"XTLDR", L"Failed to initialize debug console."); } } /* Disable watchdog timer */ Status = XtLoader::GetEfiSystemTable()->BootServices->SetWatchdogTimer(0, 0x10000, 0, NULLPTR); if(Status != STATUS_EFI_SUCCESS) { /* Failed to disable the timer, print message */ Debug::Print(L"WARNING: Failed to disable watchdog timer (Status Code: 0x%zX)\n", Status); } /* Install loader protocol */ Status = Protocol::InstallXtLoaderProtocol(); if(Status != STATUS_EFI_SUCCESS) { /* Failed to register loader protocol */ Debug::Print(L"ERROR: Failed to register XTLDR loader protocol (Status Code: 0x%zX)\n", Status); return Status; } /* Load all necessary modules */ Configuration::GetValue(L"MODULES", &Modules); Status = Protocol::LoadModules(Modules); if(Status != STATUS_EFI_SUCCESS) { /* Failed to load modules */ Debug::Print(L"ERROR: Failed to load XTLDR modules (Status Code: 0x%zX)\n", Status); TextUi::DisplayErrorDialog(L"XTLDR", L"Failed to load some XTLDR modules."); } /* Discover and enumerate EFI block devices */ Status = Volume::EnumerateBlockDevices(); if(Status != STATUS_EFI_SUCCESS) { /* Failed to enumerate block devices */ Debug::Print(L"ERROR: Failed to discover and enumerate block devices (Status Code: 0x%zX)\n", Status); return Status; } /* Main boot loader loop */ while(TRUE) { /* Show boot menu */ XtLoader::ShowBootMenu(); /* Fallback to shell, if boot menu returned */ Shell::StartLoaderShell(); } /* This point should be never reached, if this happen return error code */ return STATUS_EFI_LOAD_ERROR; } ================================================ FILE: configure.ps1 ================================================ # PROJECT: ExectOS # LICENSE: See the COPYING.md in the top level directory # FILE: configure.ps1 # DESCRIPTION: Project configuration script for preparing the build environment # DEVELOPERS: Aiken Harris # Check XTchain if (-not $env:XTCVER) { Write-Error "XTChain not detected or corrupted!" exit 1 } # Set target architecture defaulting to amd64 $ARCH = if ($env:TARGET) { $env:TARGET } else { "amd64" } # Set target build type defaulting to Debug $env:BUILD_TYPE = if ($env:BUILD_TYPE -in @("Debug", "Release")) { $env:BUILD_TYPE } else { "Debug" } # Set variables $EXECTOS_SOURCE_DIR = $PSScriptRoot $EXECTOS_BINARY_DIR = Join-Path $EXECTOS_SOURCE_DIR "build-$ARCH-$($env:BUILD_TYPE.ToLower())" # Create build directory if (-not (Test-Path $EXECTOS_BINARY_DIR)) { Write-Host "Creating build directory: $EXECTOS_BINARY_DIR" New-Item -ItemType Directory -Path $EXECTOS_BINARY_DIR -Force | Out-Null } Set-Location $EXECTOS_BINARY_DIR # Delete old cache Remove-Item "CMakeCache.txt", "host-tools/CMakeCache.txt" -ErrorAction SilentlyContinue # Configure project using CMake & cmake -G Ninja "-DARCH:STRING=$ARCH" "-DBUILD_TYPE:STRING=$($env:BUILD_TYPE)" $EXECTOS_SOURCE_DIR # Check if configuration succeeded if ($LASTEXITCODE -ne 0) { Write-Error "Configure script failed." exit 1 } $ARCH | Out-File -Encoding ASCII -NoNewline "build.arch" Write-Host "Configure completed. Run 'xbuild' to build ExectOS." ================================================ FILE: configure.sh ================================================ #!/bin/bash # PROJECT: ExectOS # LICENSE: See the COPYING.md in the top level directory # FILE: configure.sh # DESCRIPTION: Project configuration script for preparing the build environment # DEVELOPERS: Rafal Kupiec # Check XTCHain if [ "x${XTCVER}" = "x" ]; then echo "XTChain not detected or corrupted!" exit 1 fi # Set target architecture : ${ARCH:=${TARGET}} : ${ARCH:=amd64} # Set target build type : ${BUILD_TYPE:=${BUILD_TYPE}} : ${BUILD_TYPE:=DEBUG} # Set variables EXECTOS_SOURCE_DIR=$(cd `dirname ${0}` && pwd) EXECTOS_BINARY_DIR=build-${ARCH}-${BUILD_TYPE,,} # Create directories if needed if [ "${EXECTOS_SOURCE_DIR}" = "${PWD}" ]; then echo Creating directories in ${EXECTOS_BINARY_DIR} mkdir -p "${EXECTOS_BINARY_DIR}" cd "${EXECTOS_BINARY_DIR}" fi # Delete old cache rm -f CMakeCache.txt host-tools/CMakeCache.txt # Configure project cmake -G Ninja -DARCH:STRING=${ARCH} -DBUILD_TYPE:STRING=${BUILD_TYPE} "${EXECTOS_SOURCE_DIR}" # Check if configuration succeeded if [ ${?} -ne 0 ]; then echo "Configure script failed." exit 1 else echo "${ARCH}" > build.arch echo "Configure script completed. Enter '${EXECTOS_BINARY_DIR}' directory and execute 'xbuild' to build ExectOS." fi ================================================ FILE: drivers/CMakeLists.txt ================================================ add_subdirectory(ntosdrv) ================================================ FILE: drivers/ntosdrv/CMakeLists.txt ================================================ # NTOS compatibility driver PROJECT(NTOSDRV) # Specify include directories include_directories( ${EXECTOS_SOURCE_DIR}/sdk/xtdk) # Specify list of source code files list(APPEND NTOSDRV_SOURCE ${NTOSDRV_SOURCE_DIR}/ntosdrv.cc ${NTOSDRV_SOURCE_DIR}/rtl.cc) # Set module definition SPEC file set_specfile(ntosdrv.spec ntosdrv.sys) # Link bootloader executable add_executable(ntosdrv ${NTOSDRV_SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/ntosdrv.def) # Add linker libraries target_link_libraries(ntosdrv xtoskrnl) # Set proper binary name and install target set_target_properties(ntosdrv PROPERTIES SUFFIX .sys) set_install_target(ntosdrv "exectos/drivers") # Set loader entrypoint and subsystem set_entrypoint(ntosdrv "XtDriverEntry") set_linker_map(ntosdrv TRUE) set_ordinals(ntosdrv TRUE) set_subsystem(ntosdrv native xt_native_driver) ================================================ FILE: drivers/ntosdrv/ntosdrv.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: drivers/ntosdrv/ntosdrv.cc * DESCRIPTION: NTOS compatibility driver * DEVELOPERS: Rafal Kupiec */ #include /** * This routine is the entry point of the driver. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCLINK XTAPI XTSTATUS XtDriverEntry(VOID) { /* Return success */ return STATUS_SUCCESS; } ================================================ FILE: drivers/ntosdrv/ntosdrv.spec ================================================ # NT compatibilty layer exports @ fastcall ExRundownCompleted(ptr) ExCompleteRundownProtection @ stdcall RtlFillMemory(ptr long long) ================================================ FILE: drivers/ntosdrv/rtl.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: drivers/ntosdrv/rtl.cc * DESCRIPTION: NTOS compatibility driver runtime library * DEVELOPERS: Rafal Kupiec */ #include /** * This routine fills a section of memory with a specified byte. * * @param Destination * Supplies a pointer to the buffer to fill. * * @param Length * Specifies a number of bytes to store in memory. * * @param Byte * Supplies a pattern to fill memory. * * @return This routine does not return any value. * * @since NT 3.5 */ XTCLINK XTAPI VOID RtlFillMemory(OUT PVOID Destination, IN SIZE_T Length, IN UCHAR Byte) { /* Fill the buffer with specified byte */ RtlSetMemory(Destination, Byte, Length); } ================================================ FILE: sdk/CMakeLists.txt ================================================ add_subdirectory("xtadk") set_sdk_target("xtdk/" "include") ================================================ FILE: sdk/cmake/README.md ================================================ ## Cmake Build System This directory contains a set of .cmake files that provide the necessary configuration and functionality for the build process. These files provide the necessary toolchain configuration, additional functions for the build system, and QEMU configuration for testing the XT Operating System. ================================================ FILE: sdk/cmake/baseaddress/amd64.cmake ================================================ # Set base addresses for all modules set(BASEADDRESS_XTLDR 0x000000000000F800) set(BASEADDRESS_XTOSKRNL 0x0000000140000000) ================================================ FILE: sdk/cmake/baseaddress/i686.cmake ================================================ # Set base addresses for all modules set(BASEADDRESS_XTLDR 0x0000F800) set(BASEADDRESS_XTOSKRNL 0x00400000) ================================================ FILE: sdk/cmake/emulation.cmake ================================================ # Architecture specific QEMU settings if(ARCH STREQUAL i686) set(QEMU_COMMAND "qemu-system-i386") elseif(ARCH STREQUAL amd64) set(QEMU_COMMAND "qemu-system-x86_64") endif() # This target creates a disk image add_custom_target(diskimg DEPENDS install COMMAND diskimg -c ${EXECTOS_BINARY_DIR}/output/binaries -f 32 -o ${EXECTOS_BINARY_DIR}/output/disk.img -s ${PROJECT_DISK_IMAGE_SIZE} -m ${EXECTOS_BINARY_DIR}/boot/bootsect/mbrboot.bin -v ${EXECTOS_BINARY_DIR}/boot/bootsect/espboot.bin VERBATIM) find_program(BOCHS_EMULATOR bochs) if(BOCHS_EMULATOR) # This target starts up a BOCHS+BIOS virtual machine add_custom_target(bochsvm DEPENDS diskimg COMMAND bochs -f ../sdk/firmware/bochsrc_${ARCH}.cfg -q -unlock VERBATIM USES_TERMINAL) endif() find_program(QEMU_EMULATOR ${QEMU_COMMAND}) if(QEMU_EMULATOR) if(CMAKE_HOST_LINUX) # This target starts up a QEMU+OVMF virtual machine using KVM accelerator add_custom_target(testefikvm DEPENDS install COMMAND ${QEMU_COMMAND} -name "ExectOS-${ARCH}-EFI-KVM" -machine type=q35,kernel_irqchip=on,accel=kvm,mem-merge=off,vmport=off -enable-kvm -cpu host,-hypervisor,+topoext -smp 2,sockets=1,cores=1,threads=2 -m 4G -overcommit mem-lock=off -rtc clock=host,base=localtime,driftfix=none -bios ${EXECTOS_SOURCE_DIR}/sdk/firmware/ovmf_${ARCH}.fd -hda fat:rw:${EXECTOS_BINARY_DIR}/output/binaries -boot menu=on -d int -M smm=off -no-reboot -no-shutdown -serial stdio VERBATIM USES_TERMINAL) elseif(CMAKE_HOST_WIN32) # This target starts up a QEMU+OVMF virtual machine using WHPX accelerator add_custom_target(testefiwhpx DEPENDS install COMMAND ${QEMU_COMMAND} -name "ExectOS-${ARCH}-EFI-WHPX" -machine type=q35,kernel_irqchip=off,accel=whpx,mem-merge=off,vmport=off -m 4G -overcommit mem-lock=off -rtc clock=host,base=localtime,driftfix=none -bios ${EXECTOS_SOURCE_DIR}/sdk/firmware/ovmf_${ARCH}.fd -hda fat:rw:${EXECTOS_BINARY_DIR}/output/binaries -boot menu=on -d int -M smm=off -no-reboot -no-shutdown -serial stdio VERBATIM USES_TERMINAL) endif() # This target starts up a QEMU+OVMF virtual machine using TCG accelerator add_custom_target(testefitcg DEPENDS install COMMAND ${QEMU_COMMAND} -name "ExectOS-${ARCH}-EFI-TCG" -machine type=q35,accel=tcg -cpu max,-hypervisor -smp 2,sockets=1,cores=1,threads=2 -m 4G -overcommit mem-lock=off -rtc clock=host,base=localtime,driftfix=none -bios ${EXECTOS_SOURCE_DIR}/sdk/firmware/ovmf_${ARCH}.fd -hda fat:rw:${EXECTOS_BINARY_DIR}/output/binaries -boot menu=on -d int -no-reboot -no-shutdown -serial stdio VERBATIM USES_TERMINAL) if(CMAKE_HOST_LINUX) # This target starts up a QEMU+SEABIOS virtual machine using KVM accelerator add_custom_target(testkvm DEPENDS diskimg COMMAND ${QEMU_COMMAND} -name "ExectOS-${ARCH}-BIOS-KVM" -machine type=q35,kernel_irqchip=on,accel=kvm,mem-merge=off,vmport=off -enable-kvm -cpu host,-hypervisor,+topoext -smp 2,sockets=1,cores=1,threads=2 -m 4G -overcommit mem-lock=off -rtc clock=host,base=localtime,driftfix=none -hda ${EXECTOS_BINARY_DIR}/output/disk.img -boot menu=on -d int -no-reboot -no-shutdown -serial stdio VERBATIM USES_TERMINAL) elseif(CMAKE_HOST_WIN32) # This target starts up a QEMU+SEABIOS virtual machine using WHPX accelerator add_custom_target(testwhpx DEPENDS diskimg COMMAND ${QEMU_COMMAND} -name "ExectOS-${ARCH}-BIOS-WHPX" -machine type=q35,kernel_irqchip=off,accel=whpx,mem-merge=off,vmport=off -m 4G -overcommit mem-lock=off -rtc clock=host,base=localtime,driftfix=none -hda ${EXECTOS_BINARY_DIR}/output/disk.img -boot menu=on -d int -no-reboot -no-shutdown -serial stdio VERBATIM USES_TERMINAL) endif() # This target starts up a QEMU+SEABIOS virtual machine using TCG accelerator add_custom_target(testtcg DEPENDS diskimg COMMAND ${QEMU_COMMAND} -name "ExectOS-${ARCH}-BIOS-TCG" -machine type=q35,accel=tcg -cpu max,-hypervisor -smp 2,sockets=1,cores=1,threads=2 -m 4G -overcommit mem-lock=off -rtc clock=host,base=localtime,driftfix=none -hda ${EXECTOS_BINARY_DIR}/output/disk.img -boot menu=on -d int -no-reboot -no-shutdown -serial stdio VERBATIM USES_TERMINAL) endif() ================================================ FILE: sdk/cmake/functions.cmake ================================================ # This function enables the addition of ASM compiler switches function(add_compiler_asmflags FLAGS) if(NOT ${ARGC} EQUAL 1) message(FATAL_ERROR "Invalid number of arguments passed to add_compiler_asmflags() function") endif() set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${FLAGS}" PARENT_SCOPE) endfunction() # This function enables the addition of C compiler switches function(add_compiler_cflags FLAGS) if(NOT ${ARGC} EQUAL 1) message(FATAL_ERROR "Invalid number of arguments passed to add_compiler_cflags() function") endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}" PARENT_SCOPE) endfunction() # This function enables the addition of C/C++ compilers switches function(add_compiler_ccxxflags FLAGS) if(NOT ${ARGC} EQUAL 1) message(FATAL_ERROR "Invalid number of arguments passed to add_compiler_ccxxflags() function") endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}" PARENT_SCOPE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}" PARENT_SCOPE) endfunction() # This function enables the addition of C++ compiler switches function(add_compiler_cxxflags FLAGS) if(NOT ${ARGC} EQUAL 1) message(FATAL_ERROR "Invalid number of arguments passed to add_compiler_cxxflags() function") endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}" PARENT_SCOPE) endfunction() # This function enables the addition of ASM/C/C++ compilers switches function(add_compiler_flags FLAGS) if(NOT ${ARGC} EQUAL 1) message(FATAL_ERROR "Invalid number of arguments passed to add_compiler_flags() function") endif() set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${FLAGS}" PARENT_SCOPE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}" PARENT_SCOPE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}" PARENT_SCOPE) endfunction() # This function enables the addition of linker switches function(add_linker_flags FLAGS) if(NOT ${ARGC} EQUAL 1) message(FATAL_ERROR "Invalid number of arguments passwd to add_linker_flags() function") endif() foreach(TYPE EXE MODULE SHARED) set(CMAKE_${TYPE}_LINKER_FLAGS "${CMAKE_${TYPE}_LINKER_FLAGS} ${FLAGS}" PARENT_SCOPE) endforeach() endfunction() # This function enabled the addition of linker switches for specified module function(add_module_linker_flags MODULE FLAGS) if(NOT ${ARGC} EQUAL 2) message(FATAL_ERROR "Invalid number of arguments passwd to add_module_linker_flags() function") endif() set_module_property(${MODULE} LINK_FLAGS ${FLAGS}) endfunction() # This function compiles XT Assembly Development Kit function(generate_xtadk TARGET_NAME SOURCE_FILES) # Define the absolute destination path for the generated header file set(HEADER_OUTPUT "${EXECTOS_BINARY_DIR}/sdk/includes/${TARGET_NAME}.h") get_filename_component(HEADER_OUTPUT_DIRECTORY "${HEADER_OUTPUT}" DIRECTORY) # Tokenize global CXX flags into a list to ensure correct argument expansion separate_arguments(COMPILER_FLAGS NATIVE_COMMAND "${CMAKE_CXX_FLAGS}") # Resolve and tokenize build-configuration specific flags string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_TYPE) if(BUILD_TYPE) separate_arguments(BUILD_TYPE_SPECIFIC_FLAGS NATIVE_COMMAND "${CMAKE_CXX_FLAGS_${BUILD_TYPE}}") endif() # Retrieve compiler definitions, include paths, and options get_directory_property(COMPILE_DEFINITIONS COMPILE_DEFINITIONS) get_directory_property(INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES) get_directory_property(COMPILE_OPTIONS COMPILE_OPTIONS) # Initialize the final compiler argument list set(COMPILER_ARGUMENTS "") list(APPEND COMPILER_ARGUMENTS ${COMPILER_FLAGS} ${BUILD_TYPE_SPECIFIC_FLAGS}) # Transform definitions into MSVC-style foreach(DEFINITION ${COMPILE_DEFINITIONS}) list(APPEND COMPILER_ARGUMENTS "/D${DEFINITION}") endforeach() # Transform include paths into MSVC-style foreach(INCLUDE_PATH ${INCLUDE_DIRECTORIES}) list(APPEND COMPILER_ARGUMENTS "/I${INCLUDE_PATH}") endforeach() # Append all supplemental compiler options list(APPEND COMPILER_ARGUMENTS ${COMPILE_OPTIONS}) set(COLLECTED_ASSEMBLY_OUTPUTS "") # Iterate through each source file to create individual assembly generation rules foreach(SOURCE_FILE_PATH ${SOURCE_FILES}) # Extract the base filename get_filename_component(FILENAME_WITHOUT_EXTENSION "${SOURCE_FILE_PATH}" NAME_WE) # Define the unique output path for the intermediate assembly file set(CURRENT_ASSEMBLY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FILENAME_WITHOUT_EXTENSION}.S") list(APPEND COLLECTED_ASSEMBLY_OUTPUTS "${CURRENT_ASSEMBLY_OUTPUT}") get_filename_component(CURRENT_ASSEMBLY_DIRECTORY "${CURRENT_ASSEMBLY_OUTPUT}" DIRECTORY) # Execute the compiler to generate assembly code add_custom_command( OUTPUT "${CURRENT_ASSEMBLY_OUTPUT}" COMMAND ${CMAKE_COMMAND} -E make_directory "${CURRENT_ASSEMBLY_DIRECTORY}" COMMAND ${CMAKE_CXX_COMPILER} ${COMPILER_ARGUMENTS} /c /FAs /Fa${CURRENT_ASSEMBLY_OUTPUT} -- ${SOURCE_FILE_PATH} DEPENDS "${SOURCE_FILE_PATH}" COMMENT "Generating XTADK Assembly: ${FILENAME_WITHOUT_EXTENSION}" VERBATIM COMMAND_EXPAND_LISTS ) endforeach() # Aggregate all generated assembly units into a single consolidated XTADK header add_custom_command( OUTPUT "${HEADER_OUTPUT}" COMMAND ${CMAKE_COMMAND} -E make_directory "${HEADER_OUTPUT_DIRECTORY}" COMMAND xtadkgen ${COLLECTED_ASSEMBLY_OUTPUTS} -O "${HEADER_OUTPUT}" DEPENDS ${COLLECTED_ASSEMBLY_OUTPUTS} COMMENT "Generating XTADK header: ${TARGET_NAME}" VERBATIM ) # Establish the generation target and expose the header directory via an interface library add_custom_target(${TARGET_NAME}_gen DEPENDS "${HEADER_OUTPUT}") add_library(${TARGET_NAME} INTERFACE) add_dependencies(${TARGET_NAME} ${TARGET_NAME}_gen) target_include_directories(${TARGET_NAME} INTERFACE "${EXECTOS_BINARY_DIR}/sdk/includes") endfunction() # This function compiles an assembly bootsector file into a flat binary function(compile_bootsector NAME SOURCE BASEADDR ENTRYPOINT) set(BINARY_NAME "${NAME}.bin") set(OBJECT_NAME "${NAME}.obj") get_directory_property(DEFS COMPILE_DEFINITIONS) foreach(def ${DEFS}) list(APPEND ASM_DEFS "-D${def}") endforeach() add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME} COMMAND ${CMAKE_ASM_COMPILER} /nologo --target=i386-none-elf ${ASM_DEFS} -I${CMAKE_CURRENT_SOURCE_DIR} /Fo${CMAKE_CURRENT_BINARY_DIR}/${OBJECT_NAME} -c -- ${SOURCE} COMMAND ${CMAKE_ASM_LINKER} -m elf_i386 --image-base=0 --oformat binary -Ttext=${BASEADDR} --entry=_start${ENTRYPOINT} -o ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${OBJECT_NAME} DEPENDS ${SOURCE} ) add_custom_target(${NAME} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME} ) endfunction() # This function sets the the qemu disk image size (in MiB) function(set_disk_image_size SIZE) MATH(EXPR DISK_BLOCKS ${SIZE}*1024*1024/512) MATH(EXPR PART_BLOCKS ${DISK_BLOCKS}-2048) set(PROJECT_DISK_IMAGE_SIZE ${SIZE} CACHE INTERNAL "PROJECT_DISK_IMAGE_SIZE") set(PROJECT_DISK_IMAGE_BLOCKS ${DISK_BLOCKS} CACHE INTERNAL "PROJECT_DISK_IMAGE_BLOCKS") set(PROJECT_PART_IMAGE_BLOCKS ${PART_BLOCKS} CACHE INTERNAL "PROJECT_PART_IMAGE_BLOCKS") endfunction() # This function installs specified directory recursively under destination directory function(set_install_dir DIRECTORY DESTINATION) install(DIRECTORY ${DIRECTORY} DESTINATION ${EXECTOS_BINARY_DIR}/output/binaries/${DESTINATION}) endfunction() # This function installs specified file under destination directory function(set_install_file FILENAME DESTINATION) install(FILES ${FILENAME} DESTINATION ${EXECTOS_BINARY_DIR}/output/binaries/${DESTINATION}) endfunction() # This function installs specified target results under destination directory function(set_install_target TARGET DESTINATION) set_target_properties(${TARGET} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${EXECTOS_BINARY_DIR}/output/sdk/lib") install(TARGETS ${TARGET} DESTINATION ${EXECTOS_BINARY_DIR}/output/binaries/${DESTINATION}) endfunction() # This function sets a property for specified module function(set_module_property MODULE PROPERTY FLAGS) if(NOT ${ARGC} EQUAL 3) message(FATAL_ERROR "Invalid number of arguments passwd to add_module_property() function") endif() get_target_property(VAL ${MODULE} ${PROPERTY}) if(VAL) set(VAL "${VAL} ${FLAGS}") else() set(VAL "${FLAGS}") endif() set_property(TARGET ${MODULE} PROPERTY ${PROPERTY} ${VAL}) endfunction() function(set_sdk_target FILENAME DESTINATION) install(DIRECTORY ${FILENAME} DESTINATION ${EXECTOS_BINARY_DIR}/output/sdk/${DESTINATION}) endfunction() # This function is responsible for compiling module SPEC file function(set_specfile SPECFILE EXPORTNAME) if(NOT ${ARGC} EQUAL 2) message(FATAL_ERROR "Invalid number of arguments passed to set_specfile() function") endif() get_filename_component(FILENAME ${SPECFILE} NAME_WE) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${FILENAME}.def ${CMAKE_CURRENT_BINARY_DIR}/${FILENAME}.c COMMAND ${CMAKE_SPEC_COMPILER} -a=${ARCH} -n=${EXPORTNAME} -d=${CMAKE_CURRENT_BINARY_DIR}/${FILENAME}.def -s=${CMAKE_CURRENT_BINARY_DIR}/${FILENAME}.c ${CMAKE_CURRENT_SOURCE_DIR}/${SPECFILE}) endfunction() ================================================ FILE: sdk/cmake/toolchain.cmake ================================================ # Set target operating system name set(CMAKE_SYSTEM_NAME Windows) # Set toolchain compilers set(CMAKE_ASM_COMPILER clang-cl) set(CMAKE_ASM_LINKER ld.lld) set(CMAKE_C_COMPILER clang-cl) set(CMAKE_CXX_COMPILER clang-cl) set(CMAKE_LINKER lld-link) set(CMAKE_MC_COMPILER wmc) set(CMAKE_RC_COMPILER wrc) set(CMAKE_SPEC_COMPILER xtcspecc) # Assume that ASM and C/C++ compilers are working set(CMAKE_ASM_COMPILER_WORKS 1) set(CMAKE_C_COMPILER_WORKS 1) set(CMAKE_CXX_COMPILER_WORKS 1) # Set C/C++ standard and disable extensions set(CMAKE_C_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_C_STANDARD 23) set(CMAKE_CXX_STANDARD 23) # Disable standard C and C++ libraries set(CMAKE_C_STANDARD_LIBRARIES "" CACHE INTERNAL "") set(CMAKE_CXX_STANDARD_LIBRARIES "" CACHE INTERNAL "") # Clean linker flags set(CMAKE_STATIC_LINKER_FLAGS "") set(CMAKE_MODULE_LINKER_FLAGS "") set(CMAKE_EXE_LINKER_FLAGS "") set(CMAKE_SHARED_LINKER_FLAGS "") ================================================ FILE: sdk/cmake/version/xtver.h.cmake ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: includes/cmake/version/xtver.h.cmake * DESCRIPTION: XT version information - generated by toolchain * DEVELOPERS: Rafal Kupiec */ #ifndef __XTGEN_XTVER_H #define __XTGEN_XTVER_H #define XTOS_VERSION "@XTOS_VERSION_MAJOR@.@XTOS_VERSION_MINOR@-@XTOS_VERSION_BUILD@" #define XTOS_VERSION_MAJOR @XTOS_VERSION_MAJOR@ #define XTOS_VERSION_MINOR @XTOS_VERSION_MINOR@ #define XTOS_VERSION_BUILD "@XTOS_VERSION_BUILD@" #define XTOS_VERSION_HASH "@XTOS_VERSION_HASH@" #define XTOS_VERSION_ARCH "@ARCH@" #define XTOS_VERSION_DATE "@XTOS_VERSION_DATE@" #define XTOS_VERSION_FULLDATE "@XTOS_VERSION_FULLDATE@" #define XTOS_VERSION_YEAR "@XTOS_VERSION_YEAR@" #define XTOS_COMPATIBLE_MAJOR @XTOS_COMPATIBLE_MAJOR@ #define XTOS_COMPATIBLE_MINOR @XTOS_COMPATIBLE_MINOR@ #define XTOS_COMPATIBLE_BUILD @XTOS_COMPATIBLE_BUILD@ #define XTOS_COMPATIBLE_VERSION @XTOS_COMPATIBLE_VERSION@ #define XTOS_COMPATIBLE_VERSION_BUILD @XTOS_COMPATIBLE_VERSION@@XTOS_COMPATIBLE_BUILD@ #define XTOS_COMPILER_NAME "@CMAKE_C_COMPILER_ID@" #define XTOS_COMPILER_VERSION "@CMAKE_C_COMPILER_VERSION@" #define XTLDR_VERSION_MAJOR @XTLDR_VERSION_MAJOR@ #define XTLDR_VERSION_MINOR @XTLDR_VERSION_MINOR@ #endif /* __XTGEN_XTVER_H */ ================================================ FILE: sdk/cmake/version.cmake ================================================ # Set XTOS version set(XTOS_VERSION_MAJOR "0") set(XTOS_VERSION_MINOR "1") set(XTOS_VERSION_BUILD "devel") # Set XTOS NT compatibility version set(XTOS_COMPATIBLE_MAJOR "6") set(XTOS_COMPATIBLE_MINOR "3") set(XTOS_COMPATIBLE_VERSION "0x0603") set(XTOS_COMPATIBLE_BUILD "9600") # Set XTLDR version set(XTLDR_VERSION_MAJOR "0") set(XTLDR_VERSION_MINOR "1") # Set common XTOS version variables string(TIMESTAMP XTOS_VERSION_YEAR %Y) string(TIMESTAMP XTOS_VERSION_DATE "%Y%m%d") string(TIMESTAMP XTOS_VERSION_FULLDATE "%d/%m/%Y %H:%M UTC" UTC) # Set latest GIT revision set(XTOS_VERSION_HASH "unknown") if(EXISTS "${EXECTOS_SOURCE_DIR}/.git") execute_process(COMMAND git describe --abbrev=10 --long --always WORKING_DIRECTORY ${EXECTOS_SOURCE_DIR} OUTPUT_VARIABLE XTOS_VERSION_HASH OUTPUT_STRIP_TRAILING_WHITESPACE) endif() # Prepare xtver.h header file add_custom_target(xtver ALL COMMAND ${CMAKE_COMMAND} -E touch ${EXECTOS_SOURCE_DIR}/sdk/cmake/version/xtver.h.cmake) configure_file(sdk/cmake/version/xtver.h.cmake ${EXECTOS_BINARY_DIR}/sdk/includes/xtver.h) include_directories(${EXECTOS_BINARY_DIR}/sdk/includes) ================================================ FILE: sdk/cmake/xtchain.cmake ================================================ # Architecture specific flags if(ARCH STREQUAL i686) add_compiler_flags("-m32 --target=i686-pc-windows-msvc") add_linker_flags("/machine:X86") set(HOTPATCH_LINKER_FLAG "/FUNCTIONPADMIN:5") elseif(ARCH STREQUAL amd64) add_compiler_flags("-m64 --target=x86_64-pc-windows-msvc") add_linker_flags("/machine:X64") set(HOTPATCH_LINKER_FLAG "/FUNCTIONPADMIN:6") endif() # Set build optimisation if(BUILD_TYPE STREQUAL "DEBUG") add_compiler_ccxxflags("/GS- /Zi /Ob0 /Od") add_linker_flags("/DEBUG /INCREMENTAL:NO /OPT:REF /OPT:NOICF /PDBSOURCEPATH:build") else() add_compiler_ccxxflags("/GS- /Ob2 /Ot /Ox /Oy") add_linker_flags("/INCREMENTAL:NO /OPT:REF /OPT:ICF") endif() # Enable string pooling add_compiler_ccxxflags("-GF") # Disable builtin CRT library add_compiler_ccxxflags("-Zl") # Disable RTTI and buffer security checks add_compiler_ccxxflags("-GR- -GS-") # Disable thread-safe initialization add_compiler_flags("-Zc:threadSafeInit-") # Enable function level linking add_compiler_ccxxflags("-Gy") # Enable Structured Exception Handling (SEH) add_compiler_ccxxflags("-EHa") # Control warnings levels add_compiler_ccxxflags("-W3 -w14115") add_compiler_ccxxflags("-wd4200 -wd4214 -wd4244 -wd4290 -wd4800") add_compiler_ccxxflags("-we4013 -we4020 -we4022 -we4028 -we4047 -we4098 -we4101 -we4113 -we4129 -we4133") add_compiler_ccxxflags("-we4163 -we4189 -we4229 -we4311 -we4312 -we4313 -we4477 -we4603 -we4700 -we4715 -we4716") # Disable warnings about specific features add_compiler_ccxxflags("-nostdinc -Wno-char-subscripts -Wno-incompatible-library-redeclaration -Wno-microsoft-anon-tag") add_compiler_ccxxflags("-Wno-microsoft-enum-forward-reference -Wno-multichar -Wno-parentheses-equality -Wno-undefined-inline") add_compiler_ccxxflags("-Wno-gnu-folding-constant") # Disable compiler builtins add_compiler_ccxxflags("-fno-builtin") # Set symbols and libraries output directory set(CMAKE_PDB_OUTPUT_DIRECTORY "${EXECTOS_BINARY_DIR}/output/symbols") set(LIBRARY_OUTPUT_PATH "${EXECTOS_BINARY_DIR}/output/sdk/lib") # Set linker flags add_linker_flags("${HOTPATCH_LINKER_FLAG} /LARGEADDRESSAWARE /IGNORE:4039 /IGNORE:4104 /MANIFEST:NO /NODEFAULTLIB /SAFESEH:NO") # Set runtime library set(CMAKE_MSVC_RUNTIME_LIBRARY "") # Set default subsystem set(CMAKE_CREATE_CONSOLE_EXE "") # Export compile commands for clangd set(CMAKE_EXPORT_COMPILE_COMMANDS on) # This function sets entrypoint of the binary function(set_entrypoint MODULE ENTRYPOINT) if(${ENTRYPOINT} STREQUAL "0") add_module_linker_flags(${MODULE} "/NOENTRY") else() add_module_linker_flags(${MODULE} "/ENTRY:${ENTRYPOINT}") endif() endfunction() # This function sets imagebase address of the binary function(set_imagebase MODULE IMAGEBASE) add_module_linker_flags(${MODULE} "/BASE:${IMAGEBASE}") endfunction() # This function enables or disables map file generation for specified module function(set_linker_map MODULE STATE) if(NOT ${ARGC} EQUAL 2) message(FATAL_ERROR "Invalid number of arguments passed to set_ordinals() function") endif() if(STATE STREQUAL "TRUE") add_module_linker_flags(${MODULE} "/MAP:${CMAKE_CURRENT_BINARY_DIR}/${MODULE}.map") endif() endfunction() # This function enables or disables binary ordinals export for specified module function(set_ordinals MODULE STATE) if(NOT ${ARGC} EQUAL 2) message(FATAL_ERROR "Invalid number of arguments passed to set_ordinals() function") endif() set_module_property(${MODULE} ENABLE_EXPORTS ${STATE}) endfunction() # This functions sets PE/COFF subsystem and XTOS version of the binary function(set_subsystem MODULE SUBSYSTEM) string(TOUPPER ${SUBSYSTEM} SUBSYSTEM) add_module_linker_flags(${MODULE} "/SUBSYSTEM:${SUBSYSTEM},6.03") add_module_linker_flags(${MODULE} "/VERSION:6.03") if(${ARGC} EQUAL 3) set(XTSUBSYSTEM ${ARGN}) add_custom_command(TARGET ${MODULE} POST_BUILD COMMAND exetool "$" ${XTSUBSYSTEM}) endif() endfunction() ================================================ FILE: sdk/firmware/README.md ================================================ ## Open Virtual Machine Firmware (OVMF) This directory contains the essential components of the Open Virtual Machine Firmware (OVMF), which provides an open-source implementation of the Unified Extensible Firmware Interface (UEFI) for virtual machines. The ovmf_code files contain the CPU architecture specific UEFI firmware code, which serves as the initial boot code for virtual machines used to test the XTOS. It includes the necessary instructions and functions to initialize hardware, load the operating system, and provide various system services during the boot process. The ovmf_code file is responsible for establishing a UEFI environment within the virtual machine, enabling it to boot and operate effectively. The ovmf_pure files contains the minimum version of the CPU specific UEFI firmware code, suitable for use with Bochs. The ovmf_vars files, store UEFI variables, which are used to store and retrieve system configuration information, such as boot options, device settings, and system preferences. The ovmf_vars file contains the persistent variables specific to a virtual machine, allowing it to maintain its configuration across multiple boot sessions. ## BOCHS ROM BIOS The rombios.bin file contains the ROM BIOS image for Bochs. This image is distributed under the GNU Lesser General Public License (LGPL). ## Video BIOS (LGPL'd VGABios) The vgabios.bin file contains the Video Bios for Bochs and QEMU. This VGA Bios is very specific to the emulated VGA card. It is NOT meant to drive a physical vga card. It also implements support for VBE version 2.0. ================================================ FILE: sdk/firmware/bochsrc_amd64.cfg ================================================ # configuration file generated by Bochs plugin_ctrl: usb_xhci=false, serial=true, e1000=false, extfpuirq=true, parallel=true, usb_uhci=false, biosdev=true, unmapped=true, gameport=true, ne2k=false, speaker=true, iodebug=false, pcipnic=false, usb_ohci=false config_interface: textconfig display_library: x memory: host=64, guest=64 romimage: file="../sdk/firmware/rombios.bin", address=0x00000000, options=none vgaromimage: file="../sdk/firmware/vgabios.bin" boot: disk floppy_bootsig_check: disabled=0 floppya: type=1_44 # no floppyb ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata0-master: type=disk, path="output/disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Generic 1234", biosdetect=auto, translation=auto ata0-slave: type=none ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15 ata1-master: type=none ata1-slave: type=none ata2: enabled=false ata3: enabled=false optromimage1: file=none optromimage2: file=none optromimage3: file=none optromimage4: file=none optramimage1: file=none optramimage2: file=none optramimage3: file=none optramimage4: file=none pci: enabled=1, chipset=i440fx, slot1=cirrus, slot2=none, slot3=none, slot4=none, slot5=none vga: extension=cirrus, update_freq=5, realtime=1, ddc=builtin cpu: count=1:1:1, ips=400000000, quantum=16, model=corei7_sandy_bridge_2600k, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 print_timestamps: enabled=0 port_e9_hack: enabled=0 private_colormap: enabled=0 clock: sync=none, time0=local, rtc_sync=0 # no cmosimage log: - logprefix: %t%e%d debug: action=ignore info: action=report error: action=report panic: action=ask keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none mouse: type=ps2, enabled=false, toggle=ctrl+mbutton com1: enabled=true, mode=null com2: enabled=false com3: enabled=false com4: enabled=false parport1: enabled=true, file=none parport2: enabled=false speaker: enabled=true, mode=system ================================================ FILE: sdk/firmware/bochsrc_i686.cfg ================================================ # configuration file generated by Bochs plugin_ctrl: usb_xhci=false, serial=true, e1000=false, extfpuirq=true, parallel=true, usb_uhci=false, biosdev=true, unmapped=true, gameport=true, ne2k=false, speaker=true, iodebug=false, pcipnic=false, usb_ohci=false config_interface: textconfig display_library: x memory: host=64, guest=64 romimage: file="../sdk/firmware/rombios.bin", address=0x00000000, options=none vgaromimage: file="../sdk/firmware/vgabios.bin" boot: disk floppy_bootsig_check: disabled=0 floppya: type=1_44 # no floppyb ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata0-master: type=disk, path="output/disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Generic 1234", biosdetect=auto, translation=auto ata0-slave: type=none ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15 ata1-master: type=none ata1-slave: type=none ata2: enabled=false ata3: enabled=false optromimage1: file=none optromimage2: file=none optromimage3: file=none optromimage4: file=none optramimage1: file=none optramimage2: file=none optramimage3: file=none optramimage4: file=none pci: enabled=1, chipset=i440fx, slot1=cirrus, slot2=none, slot3=none, slot4=none, slot5=none vga: extension=cirrus, update_freq=5, realtime=1, ddc=builtin cpu: count=1:1:1, ips=400000000, quantum=16, model=corei7_sandy_bridge_2600k, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 print_timestamps: enabled=0 port_e9_hack: enabled=0 private_colormap: enabled=0 clock: sync=none, time0=local, rtc_sync=0 # no cmosimage log: - logprefix: %t%e%d debug: action=ignore info: action=report error: action=report panic: action=ask keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none mouse: type=ps2, enabled=false, toggle=ctrl+mbutton com1: enabled=true, mode=null com2: enabled=false com3: enabled=false com4: enabled=false parport1: enabled=true, file=none parport2: enabled=false speaker: enabled=true, mode=system ================================================ FILE: sdk/xtadk/CMakeLists.txt ================================================ # XT Assembly Development Kit PROJECT(XTADK) # Specify include directories include_directories( ${EXECTOS_SOURCE_DIR}/sdk/xtdk ${XTADK_SOURCE_DIR}/includes) # Specify list of XTADK source code files list(APPEND XTADK_SOURCE ${XTADK_SOURCE_DIR}/${ARCH}/ke.cc) # Generate assembly header from XTADK sources generate_xtadk(xtadk "${XTADK_SOURCE}") ================================================ FILE: sdk/xtadk/amd64/ke.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtadk/amd64/ke.cc * DESCRIPTION: ADK generator for AMD64 version of Kernel Library * DEVELOPERS: Aiken Harris */ #include #include /** * Generates a definitions file for the Kernel Library used by the XTOS kernel assembly code * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID GenerateAssemblyDefinitions(VOID) { /* Generate KTRAP_FRAME offsets */ ADK_OFFSET(KTRAP_FRAME, Xmm0); ADK_OFFSET(KTRAP_FRAME, Xmm1); ADK_OFFSET(KTRAP_FRAME, Xmm2); ADK_OFFSET(KTRAP_FRAME, Xmm3); ADK_OFFSET(KTRAP_FRAME, Xmm4); ADK_OFFSET(KTRAP_FRAME, Xmm5); ADK_OFFSET(KTRAP_FRAME, Xmm6); ADK_OFFSET(KTRAP_FRAME, Xmm7); ADK_OFFSET(KTRAP_FRAME, Xmm8); ADK_OFFSET(KTRAP_FRAME, Xmm9); ADK_OFFSET(KTRAP_FRAME, Xmm10); ADK_OFFSET(KTRAP_FRAME, Xmm11); ADK_OFFSET(KTRAP_FRAME, Xmm12); ADK_OFFSET(KTRAP_FRAME, Xmm13); ADK_OFFSET(KTRAP_FRAME, Xmm14); ADK_OFFSET(KTRAP_FRAME, Xmm15); ADK_OFFSET(KTRAP_FRAME, MxCsr); ADK_OFFSET(KTRAP_FRAME, PreviousMode); ADK_OFFSET(KTRAP_FRAME, Cr2); ADK_OFFSET(KTRAP_FRAME, Cr3); ADK_OFFSET(KTRAP_FRAME, Dr0); ADK_OFFSET(KTRAP_FRAME, Dr1); ADK_OFFSET(KTRAP_FRAME, Dr2); ADK_OFFSET(KTRAP_FRAME, Dr3); ADK_OFFSET(KTRAP_FRAME, Dr6); ADK_OFFSET(KTRAP_FRAME, Dr7); ADK_OFFSET(KTRAP_FRAME, SegDs); ADK_OFFSET(KTRAP_FRAME, SegEs); ADK_OFFSET(KTRAP_FRAME, SegFs); ADK_OFFSET(KTRAP_FRAME, SegGs); ADK_OFFSET(KTRAP_FRAME, Rax); ADK_OFFSET(KTRAP_FRAME, Rbx); ADK_OFFSET(KTRAP_FRAME, Rcx); ADK_OFFSET(KTRAP_FRAME, Rdx); ADK_OFFSET(KTRAP_FRAME, R8); ADK_OFFSET(KTRAP_FRAME, R9); ADK_OFFSET(KTRAP_FRAME, R10); ADK_OFFSET(KTRAP_FRAME, R11); ADK_OFFSET(KTRAP_FRAME, R12); ADK_OFFSET(KTRAP_FRAME, R13); ADK_OFFSET(KTRAP_FRAME, R14); ADK_OFFSET(KTRAP_FRAME, R15); ADK_OFFSET(KTRAP_FRAME, Rsi); ADK_OFFSET(KTRAP_FRAME, Rdi); ADK_OFFSET(KTRAP_FRAME, Rbp); ADK_OFFSET(KTRAP_FRAME, Vector); ADK_OFFSET(KTRAP_FRAME, ErrorCode); ADK_OFFSET(KTRAP_FRAME, ExceptionFrame); ADK_OFFSET(KTRAP_FRAME, Rip); ADK_OFFSET(KTRAP_FRAME, SegCs); ADK_OFFSET(KTRAP_FRAME, Flags); ADK_OFFSET(KTRAP_FRAME, Rsp); ADK_OFFSET(KTRAP_FRAME, SegSs); /* Generate KTRAP_FRAME size and REGISTERS_SIZE */ ADK_SIZE(KTRAP_FRAME); ADK_SIZE_FROM(REGISTERS_SIZE, KTRAP_FRAME, Rax); /* Generate PROCESSOR_START_BLOCK offsets */ ADK_OFFSET(PROCESSOR_START_BLOCK, Cr3); ADK_OFFSET(PROCESSOR_START_BLOCK, Cr4); ADK_OFFSET(PROCESSOR_START_BLOCK, EntryPoint); ADK_OFFSET(PROCESSOR_START_BLOCK, ProcessorStructures); ADK_OFFSET(PROCESSOR_START_BLOCK, Stack); ADK_OFFSET(PROCESSOR_START_BLOCK, Started); } ================================================ FILE: sdk/xtadk/i686/ke.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtadk/i686/ke.cc * DESCRIPTION: ADK generator for i686 version of Kernel Library * DEVELOPERS: Aiken Harris */ #include #include /** * Generates a definitions file for the Kernel Library used by the XTOS kernel assembly code * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID GenerateAssemblyDefinitions(VOID) { /* Generate KTRAP_FRAME offsets */ ADK_OFFSET(KTRAP_FRAME, PreviousMode); ADK_OFFSET(KTRAP_FRAME, Cr2); ADK_OFFSET(KTRAP_FRAME, Cr3); ADK_OFFSET(KTRAP_FRAME, Dr0); ADK_OFFSET(KTRAP_FRAME, Dr1); ADK_OFFSET(KTRAP_FRAME, Dr2); ADK_OFFSET(KTRAP_FRAME, Dr3); ADK_OFFSET(KTRAP_FRAME, Dr6); ADK_OFFSET(KTRAP_FRAME, Dr7); ADK_OFFSET(KTRAP_FRAME, SegDs); ADK_OFFSET(KTRAP_FRAME, SegEs); ADK_OFFSET(KTRAP_FRAME, SegFs); ADK_OFFSET(KTRAP_FRAME, SegGs); ADK_OFFSET(KTRAP_FRAME, Eax); ADK_OFFSET(KTRAP_FRAME, Ebx); ADK_OFFSET(KTRAP_FRAME, Ecx); ADK_OFFSET(KTRAP_FRAME, Edx); ADK_OFFSET(KTRAP_FRAME, Esi); ADK_OFFSET(KTRAP_FRAME, Edi); ADK_OFFSET(KTRAP_FRAME, Ebp); ADK_OFFSET(KTRAP_FRAME, Vector); ADK_OFFSET(KTRAP_FRAME, ErrorCode); ADK_OFFSET(KTRAP_FRAME, Eip); ADK_OFFSET(KTRAP_FRAME, SegCs); ADK_OFFSET(KTRAP_FRAME, Flags); ADK_OFFSET(KTRAP_FRAME, Esp); ADK_OFFSET(KTRAP_FRAME, SegSs); /* Generate KTRAP_FRAME size and REGISTERS_SIZE */ ADK_SIZE(KTRAP_FRAME); ADK_SIZE_FROM(REGISTERS_SIZE, KTRAP_FRAME, Eax); /* Generate PROCESSOR_START_BLOCK offsets */ ADK_OFFSET(PROCESSOR_START_BLOCK, Cr3); ADK_OFFSET(PROCESSOR_START_BLOCK, Cr4); ADK_OFFSET(PROCESSOR_START_BLOCK, EntryPoint); ADK_OFFSET(PROCESSOR_START_BLOCK, ProcessorStructures); ADK_OFFSET(PROCESSOR_START_BLOCK, Stack); ADK_OFFSET(PROCESSOR_START_BLOCK, Started); } ================================================ FILE: sdk/xtadk/includes/adkdefs.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtadk/adkdefs.h * DESCRIPTION: Definitions for XTADK * DEVELOPERS: Aiken Harris */ #ifndef __XTADK_ADKDEFS_H #define __XTADK_ADKDEFS_H /* Macros for calculating structure size and offsets for assembler code */ #define ADK_DEFINE(Symbol, Value) __asm__ volatile("\n\t# ==> " #Symbol " %c0" : : "i" ((SIZE_T)(Value))) #define ADK_OFFSET(Structure, Member) ADK_DEFINE(Structure ## _ ## Member, FIELD_OFFSET(Structure, Member)) #define ADK_SIZE(Structure) ADK_DEFINE(Structure ## _SIZE, sizeof(Structure)) #define ADK_SIZE_FROM(Name, Structure, Member) ADK_DEFINE(Structure ## _ ## Name, sizeof(Structure) - FIELD_OFFSET(Structure, Member)) #endif /* __XTADK_ADKDEFS_H */ ================================================ FILE: sdk/xtdk/README.md ================================================ ## XT Development Kit (XTDK) The XTDK, or XT Development Kit is a comprehensive set of headers designed to facilitate the development of both kernel mode drivers and native XT applications. It includes two main headers: xtkmapi.h and xtumapi.h. The xtkmapi.h header is primarily used for kernel mode development, specifically for building drivers. It provides developers with the necessary definitions and functions required to interact with the kernel and access system resources. With this header, developers can write efficient and secure kernel mode drivers for the XT operating system. The xtumapi.h header is tailored for user mode development. It encompasses all the essential components needed for creating user mode applications on the XT platform. This header exposes the definitions and public functions exported by XTOS, allowing developers to leverage the capabilities of the operating system and build powerful user mode applications. By utilizing XTDK, developers can harness the full potential of the XT operating system and seamlessly write both kernel mode drivers and user mode applications. The provided headers streamline the development process by offering a standardized set of functions and definitions, reducing the complexity and effort required to create software for the XT platform. ================================================ FILE: sdk/xtdk/amd64/artypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/amd64/artypes.h * DESCRIPTION: AMD64 architecture library structure definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_AMD64_ARTYPES_H #define __XTDK_AMD64_ARTYPES_H #include #include #include #include ARCH_HEADER(xtstruct.h) /* Control Register 0 constants */ #define CR0_PE 0x00000001 #define CR0_MP 0x00000002 #define CR0_EM 0x00000004 #define CR0_TS 0x00000008 #define CR0_ET 0x00000010 #define CR0_NE 0x00000020 #define CR0_WP 0x00010000 #define CR0_AM 0x00040000 #define CR0_NW 0x20000000 #define CR0_CD 0x40000000 #define CR0_PG 0x80000000 /* Control Register 4 constants */ #define CR4_VME 0x00000001 #define CR4_PVI 0x00000002 #define CR4_TSD 0x00000004 #define CR4_DE 0x00000008 #define CR4_PSE 0x00000010 #define CR4_PAE 0x00000020 #define CR4_MCE 0x00000040 #define CR4_PGE 0x00000080 #define CR4_PCE 0x00000100 #define CR4_FXSR 0x00000200 #define CR4_XMMEXCPT 0x00000400 #define CR4_UMIP 0x00000800 #define CR4_LA57 0x00001000 #define CR4_VMXE 0x00002000 #define CR4_SMXE 0x00004000 #define CR4_FSGSBASE 0x00010000 #define CR4_PCIDE 0x00020000 #define CR4_XSAVE 0x00040000 #define CR4_KL 0x00080000 #define CR4_SMEP 0x00100000 #define CR4_SMAP 0x00200000 #define CR4_PKE 0x00400000 #define CR4_CET 0x00800000 #define CR4_PKS 0x01000000 #define CR4_UINTR 0x02000000 #define CR4_LASS 0x08000000 #define CR4_LAM_SUP 0x10000000 /* Descriptors size */ #define GDT_ENTRIES 128 #define IDT_ENTRIES 256 /* Initial MXCSR control */ #define INITIAL_MXCSR 0x1F80 /* Page Attributes Table types */ #define PAT_TYPE_STRONG_UC 0ULL #define PAT_TYPE_USWC 1ULL #define PAT_TYPE_WT 4ULL #define PAT_TYPE_WP 5ULL #define PAT_TYPE_WB 6ULL #define PAT_TYPE_WEAK_UC 7ULL /* Segment defintions */ #define SEGMENT_CS 0x2E #define SEGMENT_DS 0x3E #define SEGMENT_ES 0x26 #define SEGMENT_SS 0x36 #define SEGMENT_FS 0x64 #define SEGMENT_GS 0x65 /* MSR values */ #define X86_MSR_SYSENTER_CS 0x00000174 #define X86_MSR_SYSENTER_ESP 0x00000175 #define X86_MSR_SYSENTER_EIP 0x00000176 #define X86_MSR_POWER_CONTROL 0x000001FC #define X86_MSR_PAT 0x00000277 #define X86_MSR_EFER 0xC0000080 #define X86_MSR_STAR 0xC0000081 #define X86_MSR_LSTAR 0xC0000082 #define X86_MSR_CSTAR 0xC0000083 #define X86_MSR_FMASK 0xC0000084 #define X86_MSR_FSBASE 0xC0000100 #define X86_MSR_GSBASE 0xC0000101 #define X86_MSR_KERNEL_GSBASE 0xC0000102 #define X86_MSR_TSC_AUX 0xC0000103 /* Processor features in the EFER MSR */ #define X86_MSR_EFER_SCE (1 << 0) #define X86_MSR_EFER_LME (1 << 8) #define X86_MSR_EFER_LMA (1 << 10) #define X86_MSR_EFER_NXE (1 << 11) #define X86_MSR_EFER_SVME (1 << 12) #define X86_EFER_LMSLE (1 << 13) #define X86_EFER_FFXSR (1 << 14) #define X86_EFER_TCE (1 << 15) #define X86_EFER_AUTOIBRS (1 << 21) /* X86 EFLAG bit masks definitions */ #define X86_EFLAGS_NF_MASK 0x00000000 /* None */ #define X86_EFLAGS_CF_MASK 0x00000001 /* Carry */ #define X86_EFLAGS_PF_MASK 0x00000004 /* Parity */ #define X86_EFALGS_AF_MASK 0x00000010 /* Aux Carry */ #define X86_EFLAGS_ZF_MASK 0x00000040 /* Zero */ #define X86_EFLAGS_SF_MASK 0x00000080 /* Sign */ #define X86_EFLAGS_TF_MASK 0x00000100 /* Trap */ #define X86_EFLAGS_IF_MASK 0x00000200 /* Interrupt */ #define X86_EFLAGS_DF_MASK 0x00000400 /* Direction */ #define X86_EFLAGS_OF_MASK 0x00000800 /* Overflow */ #define X86_EFLAGS_IOPL_MASK 0x00003000 /* I/O Privilege */ #define X86_EFLAGS_NT_MASK 0x00004000 /* Nested Task */ #define X86_EFLAGS_SIGN_MASK 0x00008000 /* Sign */ #define X86_EFLAGS_RF_MASK 0x00010000 /* Resume */ #define X86_EFLAGS_V86_MASK 0x00020000 /* Virtual 8086 */ #define X86_EFLAGS_AC_MASK 0x00040000 /* Alignment Check */ #define X86_EFLAGS_VIF_MASK 0x00080000 /* Virtual Interrupt */ #define X86_EFLAGS_VIP_MASK 0x00100000 /* Virtual Interrupt Pending */ #define X86_EFLAGS_ID_MASK 0x00200000 /* Identification */ /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* CPU vendor enumeration list */ typedef enum _CPU_VENDOR { CPU_VENDOR_AMD = 0x68747541, CPU_VENDOR_INTEL = 0x756E6547, CPU_VENDOR_UNKNOWN = 0xFFFFFFFF } CPU_VENDOR, *PCPU_VENDOR; /* CPUID advanced power management features (0x80000007) enumeration list */ typedef enum _CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT { CPUID_FEATURES_EDX_TS = 1 << 0, /* Temperature Sensor */ CPUID_FEATURES_EDX_FIS = 1 << 1, /* Frequency ID Selection */ CPUID_FEATURES_EDX_VIS = 1 << 2, /* Voltage ID Selection */ CPUID_FEATURES_EDX_TTS = 1 << 3, /* ThermaTrip Support */ CPUID_FEATURES_EDX_HTC = 1 << 4, /* Hardware Thermal Throttling */ CPUID_FEATURES_EDX_STC = 1 << 5, /* Software Thermal Throttling */ CPUID_FEATURES_EDX_TSCI = 1 << 8 /* TSC Invariant */ } CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT, *PCPUID_FEATURES_ADVANCED_POWER_MANAGEMENT; /* CPUID extended features (0x80000001) enumeration list */ typedef enum _CPUID_FEATURES_EXTENDED { CPUID_FEATURES_ECX_LAHF_SAHF = 1 << 0, CPUID_FEATURES_ECX_CMP_LEGACY = 1 << 1, CPUID_FEATURES_ECX_SVM = 1 << 2, CPUID_FEATURES_ECX_EXT_APIC_SPACE = 1 << 3, CPUID_FEATURES_ECX_ALT_MOV_CR8 = 1 << 4, CPUID_FEATURES_ECX_LZCNT = 1 << 5, CPUID_FEATURES_ECX_SSE4A = 1 << 6, CPUID_FEATURES_ECX_MISALIGNED_SSE = 1 << 7, CPUID_FEATURES_ECX_PREFETCHW = 1 << 8, CPUID_FEATURES_ECX_OSVW = 1 << 9, CPUID_FEATURES_ECX_IBS = 1 << 10, CPUID_FEATURES_ECX_XOP = 1 << 11, CPUID_FEATURES_ECX_SKINIT = 1 << 12, CPUID_FEATURES_ECX_WDT = 1 << 13, CPUID_FEATURES_ECX_LWP = 1 << 15, CPUID_FEATURES_ECX_FMA4 = 1 << 16, CPUID_FEATURES_ECX_TCE = 1 << 17, CPUID_FEATURES_ECX_NODEID = 1 << 19, CPUID_FEATURES_ECX_TBM = 1 << 21, CPUID_FEATURES_ECX_TOPOLOGY_EXTENSIONS = 1 << 22, CPUID_FEATURES_ECX_PERFCTR_EXT_CORE = 1 << 23, CPUID_FEATURES_ECX_PERFCTR_EXT_NB = 1 << 24, CPUID_FEATURES_ECX_DATA_BREAKPOINT_EXT = 1 << 26, CPUID_FEATURES_ECX_PERF_TSC = 1 << 27, CPUID_FEATURES_ECX_PERFCTR_EXT_L2I = 1 << 28, CPUID_FEATURES_ECX_MONITORX_MWAITX = 1 << 29, CPUID_FEATURES_ECX_CODEBP_ADDRMASK_EXT = 1 << 30, CPUID_FEATURES_EDX_SYSCALL_SYSRET = 1 << 11, CPUID_FEATURES_EDX_NX = 1 << 20, CPUID_FEATURES_EDX_AMD_MMX_EXT = 1 << 22, CPUID_FEATURES_EDX_FFXSR = 1 << 25, CPUID_FEATURES_EDX_1G_PAGES = 1 << 26, CPUID_FEATURES_EDX_RDTSCP = 1 << 27, CPUID_FEATURES_EDX_LONG_MODE = 1 << 29, CPUID_FEATURES_EDX_3DNOW_EXT = 1 << 30, CPUID_FEATURES_EDX_3DNOW = 1 << 31 } CPUID_FEATURES_EXTENDED, *PCPUID_FEATURES_EXTENDED; /* CPUID Thermal and Power Management features (0x00000006) enumeration list */ typedef enum _CPUID_FEATURES_POWER_MANAGEMENT { CPUID_FEATURES_EAX_DTHERM = 1 << 0, CPUID_FEATURES_EAX_IDA = 1 << 1, CPUID_FEATURES_EAX_ARAT = 1 << 2, CPUID_FEATURES_EAX_PLN = 1 << 4, CPUID_FEATURES_EAX_PTS = 1 << 6, CPUID_FEATURES_EAX_HWP = 1 << 7, CPUID_FEATURES_EAX_HWP_NOTIFY = 1 << 8, CPUID_FEATURES_EAX_HWP_ACT_WINDOW = 1 << 9, CPUID_FEATURES_EAX_HWP_EPP = 1 << 10, CPUID_FEATURES_EAX_HWP_PKG_REQ = 1 << 11, CPUID_FEATURES_EAX_HWP_HIGHEST_PERF_CHANGE = 1 << 15, CPUID_FEATURES_EAX_HFI = 1 << 19 } CPUID_FEATURES_LEAF6, *PCPUID_FEATURES_LEAF6; /* CPUID STD1 features (0x00000001) enumeration list */ typedef enum _CPUID_FEATURES_STANDARD1 { CPUID_FEATURES_ECX_SSE3 = 1 << 0, CPUID_FEATURES_ECX_PCLMUL = 1 << 1, CPUID_FEATURES_ECX_DTES64 = 1 << 2, CPUID_FEATURES_ECX_MONITOR = 1 << 3, CPUID_FEATURES_ECX_DS_CPL = 1 << 4, CPUID_FEATURES_ECX_VMX = 1 << 5, CPUID_FEATURES_ECX_SMX = 1 << 6, CPUID_FEATURES_ECX_EST = 1 << 7, CPUID_FEATURES_ECX_TM2 = 1 << 8, CPUID_FEATURES_ECX_SSSE3 = 1 << 9, CPUID_FEATURES_ECX_CID = 1 << 10, CPUID_FEATURES_ECX_SDBG = 1 << 11, CPUID_FEATURES_ECX_FMA = 1 << 12, CPUID_FEATURES_ECX_CX16 = 1 << 13, CPUID_FEATURES_ECX_XTPR = 1 << 14, CPUID_FEATURES_ECX_PDCM = 1 << 15, CPUID_FEATURES_ECX_PCID = 1 << 17, CPUID_FEATURES_ECX_DCA = 1 << 18, CPUID_FEATURES_ECX_SSE4_1 = 1 << 19, CPUID_FEATURES_ECX_SSE4_2 = 1 << 20, CPUID_FEATURES_ECX_X2APIC = 1 << 21, CPUID_FEATURES_ECX_MOVBE = 1 << 22, CPUID_FEATURES_ECX_POPCNT = 1 << 23, CPUID_FEATURES_ECX_TSC_DEADLINE = 1 << 24, CPUID_FEATURES_ECX_AES = 1 << 25, CPUID_FEATURES_ECX_XSAVE = 1 << 26, CPUID_FEATURES_ECX_OSXSAVE = 1 << 27, CPUID_FEATURES_ECX_AVX = 1 << 28, CPUID_FEATURES_ECX_F16C = 1 << 29, CPUID_FEATURES_ECX_RDRAND = 1 << 30, CPUID_FEATURES_ECX_HYPERVISOR = 1 << 31, CPUID_FEATURES_EDX_FPU = 1 << 0, CPUID_FEATURES_EDX_VME = 1 << 1, CPUID_FEATURES_EDX_DE = 1 << 2, CPUID_FEATURES_EDX_PSE = 1 << 3, CPUID_FEATURES_EDX_TSC = 1 << 4, CPUID_FEATURES_EDX_MSR = 1 << 5, CPUID_FEATURES_EDX_PAE = 1 << 6, CPUID_FEATURES_EDX_MCE = 1 << 7, CPUID_FEATURES_EDX_CX8 = 1 << 8, CPUID_FEATURES_EDX_APIC = 1 << 9, CPUID_FEATURES_EDX_SEP = 1 << 11, CPUID_FEATURES_EDX_MTRR = 1 << 12, CPUID_FEATURES_EDX_PGE = 1 << 13, CPUID_FEATURES_EDX_MCA = 1 << 14, CPUID_FEATURES_EDX_CMOV = 1 << 15, CPUID_FEATURES_EDX_PAT = 1 << 16, CPUID_FEATURES_EDX_PSE36 = 1 << 17, CPUID_FEATURES_EDX_PSN = 1 << 18, CPUID_FEATURES_EDX_CLFLUSH = 1 << 19, CPUID_FEATURES_EDX_DS = 1 << 21, CPUID_FEATURES_EDX_ACPI = 1 << 22, CPUID_FEATURES_EDX_MMX = 1 << 23, CPUID_FEATURES_EDX_FXSR = 1 << 24, CPUID_FEATURES_EDX_SSE = 1 << 25, CPUID_FEATURES_EDX_SSE2 = 1 << 26, CPUID_FEATURES_EDX_SS = 1 << 27, CPUID_FEATURES_EDX_HTT = 1 << 28, CPUID_FEATURES_EDX_TM = 1 << 29, CPUID_FEATURES_EDX_IA64 = 1 << 30, CPUID_FEATURES_EDX_PBE = 1 << 31 } CPUID_FEATURES_STANDARD1, *PCPUID_FEATURES_STANDARD1; /* CPUID STD7 features (0x00000007, subleaf 0) enumeration list */ typedef enum _CPUID_FEATURES_STANDARD7_LEAF0 { CPUID_FEATURES_EBX_FSGSBASE = 1 << 0, CPUID_FEATURES_EBX_TSC_ADJUST = 1 << 1, CPUID_FEATURES_EBX_SGX = 1 << 2, CPUID_FEATURES_EBX_BMI1 = 1 << 3, CPUID_FEATURES_EBX_HLE = 1 << 4, CPUID_FEATURES_EBX_AVX2 = 1 << 5, CPUID_FEATURES_EBX_FDP_DEPRECATION = 1 << 6, CPUID_FEATURES_EBX_SMEP = 1 << 7, CPUID_FEATURES_EBX_BMI2 = 1 << 8, CPUID_FEATURES_EBX_ERMS = 1 << 9, CPUID_FEATURES_EBX_INVPCID = 1 << 10, CPUID_FEATURES_EBX_RTM = 1 << 11, CPUID_FEATURES_EBX_QOS_MONITORING = 1 << 12, CPUID_FEATURES_EBX_DEPRECATE_FCS_FDS = 1 << 13, CPUID_FEATURES_EBX_MPX = 1 << 14, CPUID_FEATURES_EBX_QOS_ENFORCEMENT = 1 << 15, CPUID_FEATURES_EBX_AVX512F = 1 << 16, CPUID_FEATURES_EBX_AVX512DQ = 1 << 17, CPUID_FEATURES_EBX_RDSEED = 1 << 18, CPUID_FEATURES_EBX_ADX = 1 << 19, CPUID_FEATURES_EBX_SMAP = 1 << 20, CPUID_FEATURES_EBX_AVX512IFMA52 = 1 << 21, CPUID_FEATURES_EBX_CLFLUSHOPT = 1 << 23, CPUID_FEATURES_EBX_CLWB = 1 << 24, CPUID_FEATURES_EBX_PROCESSOR_TRACE = 1 << 25, CPUID_FEATURES_EBX_AVX512PF = 1 << 26, CPUID_FEATURES_EBX_AVX512ER = 1 << 27, CPUID_FEATURES_EBX_AVX512CD = 1 << 28, CPUID_FEATURES_EBX_SHA = 1 << 29, CPUID_FEATURES_EBX_AVX512BW = 1 << 30, CPUID_FEATURES_EBX_AVX512VL = 1 << 31, CPUID_FEATURES_ECX_PREFETCHWT1 = 1 << 0, CPUID_FEATURES_ECX_AVX512_VBMI = 1 << 1, CPUID_FEATURES_ECX_UMIP = 1 << 2, CPUID_FEATURES_ECX_PKU = 1 << 3, CPUID_FEATURES_ECX_OSPKE = 1 << 4, CPUID_FEATURES_ECX_WAITPKG = 1 << 5, CPUID_FEATURES_ECX_AVX512_VBMI2 = 1 << 6, CPUID_FEATURES_ECX_CET_SS = 1 << 7, CPUID_FEATURES_ECX_GFNI = 1 << 8, CPUID_FEATURES_ECX_VAES = 1 << 9, CPUID_FEATURES_ECX_VPCLMULQDQ = 1 << 10, CPUID_FEATURES_ECX_AVX512_VNNI = 1 << 11, CPUID_FEATURES_ECX_AVX512_BITALG = 1 << 12, CPUID_FEATURES_ECX_TME = 1 << 13, CPUID_FEATURES_ECX_AVX512_VPOPCNTDQ = 1 << 14, CPUID_FEATURES_ECX_LA57 = 1 << 16, CPUID_FEATURES_ECX_RDPID = 1 << 22, CPUID_FEATURES_ECX_KEYLOCKER = 1 << 23, CPUID_FEATURES_ECX_BUS_LOCK_DETECT = 1 << 24, CPUID_FEATURES_ECX_CLDEMOTE = 1 << 25, CPUID_FEATURES_ECX_MOVDIRI = 1 << 27, CPUID_FEATURES_ECX_MOVDIR64B = 1 << 28, CPUID_FEATURES_ECX_ENQCMD = 1 << 29, CPUID_FEATURES_ECX_SGX_LAUNCH_CONFIG = 1 << 30, CPUID_FEATURES_ECX_PKS = 1 << 31, CPUID_FEATURES_EDX_SGX_KEYS = 1 << 1, CPUID_FEATURES_EDX_AVX512_4VNNIW = 1 << 2, CPUID_FEATURES_EDX_AVX512_4FMAPS = 1 << 3, CPUID_FEATURES_EDX_FAST_SHORT_REP_MOV = 1 << 4, CPUID_FEATURES_EDX_UINTR = 1 << 5, CPUID_FEATURES_EDX_AVX512_VPINTERSECT = 1 << 8, CPUID_FEATURES_EDX_SRBDS_CTRL = 1 << 9, CPUID_FEATURES_EDX_MD_CLEAR = 1 << 10, CPUID_FEATURES_EDX_RTM_ALWAYS_ABORT = 1 << 11, CPUID_FEATURES_EDX_RTM_FORCE_ABORT = 1 << 13, CPUID_FEATURES_EDX_SERIALIZE = 1 << 14, CPUID_FEATURES_EDX_HYBRID = 1 << 15, CPUID_FEATURES_EDX_TSXLDTRK = 1 << 16, CPUID_FEATURES_EDX_PCONFIG = 1 << 18, CPUID_FEATURES_EDX_ARCH_LBR = 1 << 19, CPUID_FEATURES_EDX_CET_IBT = 1 << 20, CPUID_FEATURES_EDX_AMX_BF16 = 1 << 22, CPUID_FEATURES_EDX_AVX512_FP16 = 1 << 23, CPUID_FEATURES_EDX_AMX_TILE = 1 << 24, CPUID_FEATURES_EDX_AMX_INT8 = 1 << 25, CPUID_FEATURES_EDX_SCA_IBRS_IBPB = 1 << 26, CPUID_FEATURES_EDX_SCA_STIBP = 1 << 27, CPUID_FEATURES_EDX_L1D_FLUSH = 1 << 28, CPUID_FEATURES_EDX_ARCH_CAPABILITIES_MSR = 1 << 29, CPUID_FEATURES_EDX_CORE_CAPABILITIES_MSR = 1 << 30, CPUID_FEATURES_EDX_SCA_SSBD = 1 << 31 } CPUID_FEATURES_STANDARD7_LEAF0, *PCPUID_FEATURES_STANDARD7_LEAF0; /* CPUID STD7 features (0x00000007, subleaf 1) enumeration list */ typedef enum _CPUID_FEATURES_STANDARD7_LEAF1 { CPUID_FEATURES_EAX_SHA512 = 1 << 0, CPUID_FEATURES_EAX_SM3 = 1 << 1, CPUID_FEATURES_EAX_SM4 = 1 << 2, CPUID_FEATURES_EAX_RAO_INT = 1 << 3, CPUID_FEATURES_EAX_AVX_VNNI = 1 << 4, CPUID_FEATURES_EAX_AVX512_BF16 = 1 << 5, CPUID_FEATURES_EAX_LASS = 1 << 6, CPUID_FEATURES_EAX_CMPCCXADD = 1 << 7, CPUID_FEATURES_EAX_ARCH_PERFMON = 1 << 8, CPUID_FEATURES_EAX_FAST_ZEROLEN_REP_MOVSB = 1 << 10, CPUID_FEATURES_EAX_FAST_ZEROLEN_REP_STOSB = 1 << 11, CPUID_FEATURES_EAX_FAST_ZEROLEN_REP_CMPSB = 1 << 12, CPUID_FEATURES_EAX_FRED = 1 << 17, CPUID_FEATURES_EAX_LKGS = 1 << 18, CPUID_FEATURES_EAX_WRMSRNS = 1 << 19, CPUID_FEATURES_EAX_NMI_SOURCE_REPORTING = 1 << 20, CPUID_FEATURES_EAX_AMX_FP16 = 1 << 21, CPUID_FEATURES_EAX_HRESET = 1 << 22, CPUID_FEATURES_EAX_AVX_IFMA = 1 << 23, CPUID_FEATURES_EAX_LAM = 1 << 26, CPUID_FEATURES_EAX_MSRLIST = 1 << 27, CPUID_FEATURES_EAX_INVD_DISABLE = 1 << 30, CPUID_FEATURES_EAX_MOVRS = 1 << 31, CPUID_FEATURES_EBX_PPIN = 1 << 0, CPUID_FEATURES_EBX_TSE = 1 << 1, CPUID_FEATURES_EBX_CPUIDMAXVAL_LIM_RMV = 1 << 3, CPUID_FEATURES_ECX_MSR_IMM = 1 << 5, CPUID_FEATURES_EDX_AVX_VNNI_INT8 = 1 << 4, CPUID_FEATURES_EDX_AVX_NE_CONVERT = 1 << 5, CPUID_FEATURES_EDX_AMX_COMPLEX = 1 << 8, CPUID_FEATURES_EDX_AVX_VNNI_INT16 = 1 << 10, CPUID_FEATURES_EDX_USER_TIMER = 1 << 13, CPUID_FEATURES_EDX_PREFETCHI = 1 << 14, CPUID_FEATURES_EDX_USER_MSR = 1 << 15, CPUID_FEATURES_EDX_UIRET_UIF = 1 << 17, CPUID_FEATURES_EDX_CET_SSS = 1 << 18, CPUID_FEATURES_EDX_AVX10 = 1 << 19, CPUID_FEATURES_EDX_APX = 1 << 21, CPUID_FEATURES_EDX_MWAIT_AND_LEAF5 = 1 << 23 } CPUID_FEATURES_STANDARD7_LEAF1, *PCPUID_FEATURES_STANDARD7_LEAF1; /* CPUID requests */ typedef enum _CPUID_REQUESTS { CPUID_GET_VENDOR_STRING = 0x00000000, CPUID_GET_STANDARD1_FEATURES = 0x00000001, CPUID_GET_TLB_CACHE = 0x00000002, CPUID_GET_SERIAL = 0x00000003, CPUID_GET_CACHE_TOPOLOGY = 0x00000004, CPUID_GET_MONITOR_MWAIT = 0x00000005, CPUID_GET_POWER_MANAGEMENT = 0x00000006, CPUID_GET_STANDARD7_FEATURES = 0x00000007, CPUID_GET_TSC_CRYSTAL_CLOCK = 0x00000015, CPUID_GET_EXTENDED_MAX = 0x80000000, CPUID_GET_EXTENDED_FEATURES = 0x80000001, CPUID_GET_ADVANCED_POWER_MANAGEMENT = 0x80000007 } CPUID_REQUESTS, *PCPUID_REQUESTS; /* Interrupt handler */ typedef VOID (*PINTERRUPT_HANDLER)(PKTRAP_FRAME TrapFrame); /* Processor identification information */ typedef struct _CPU_IDENTIFICATION { ULONGLONG ExtendedFeatureBits; USHORT Family; ULONGLONG FeatureBits; USHORT Model; USHORT Stepping; CPU_VENDOR Vendor; UCHAR VendorName[13]; } CPU_IDENTIFICATION, *PCPU_IDENTIFICATION; /* CPUID registers */ typedef struct _CPUID_REGISTERS { UINT32 Leaf; UINT32 SubLeaf; UINT32 Eax; UINT32 Ebx; UINT32 Ecx; UINT32 Edx; } CPUID_REGISTERS, *PCPUID_REGISTERS; /* CPU signature read from CPUID structure definition */ typedef struct _CPUID_SIGNATURE { ULONG Stepping:4; ULONG Model:4; ULONG Family:4; ULONG Unused1:4; ULONG ExtendedModel:4; ULONG ExtendedFamily:8; ULONG Unused2:4; } CPU_SIGNATURE, *PCPU_SIGNATURE; /* Trampoline types */ typedef enum _TRAMPOLINE_TYPE { TrampolineApStartup, TrampolineEnableXpa } TRAMPOLINE_TYPE, *PTRAMPOLINE_TYPE; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_AMD64_ARTYPES_H */ ================================================ FILE: sdk/xtdk/amd64/hlfuncs.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/amd64/hlfuncs.h * DESCRIPTION: XT hardware abstraction layer routines specific to AMD64 architecture * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_AMD64_HLFUNCS_H #define __XTDK_AMD64_HLFUNCS_H #include #include #include #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Hardware layer routines forward references */ XTCLINK XTCDECL UCHAR HlReadPort8(IN USHORT Port); XTCLINK XTCDECL USHORT HlReadPort16(IN USHORT Port); XTCLINK XTCDECL ULONG HlReadPort32(IN USHORT Port); XTCLINK XTCDECL VOID HlWritePort8(IN USHORT Port, IN UCHAR Data); XTCLINK XTCDECL VOID HlWritePort16(IN USHORT Port, IN USHORT Value); XTCLINK XTCDECL VOID HlWritePort32(IN USHORT Port, IN ULONG Value); #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_AMD64_HLFUNCS_H */ ================================================ FILE: sdk/xtdk/amd64/hltypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/amd64/hltypes.h * DESCRIPTION: XT hardware abstraction layer structures definitions specific to AMD64 architecture * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_AMD64_HLTYPES_H #define __XTDK_AMD64_HLTYPES_H #include #include #include #include #include ARCH_HEADER(xtstruct.h) /* APIC base addresses */ #define APIC_BASE 0xFFFFFFFFFFFE0000 #define APIC_LAPIC_MSR_BASE 0x0000001B #define APIC_X2APIC_MSR_BASE 0x00000800 /* APIC vector definitions */ #define APIC_VECTOR_ZERO 0x00 #define APIC_VECTOR_APC 0x1F #define APIC_VECTOR_DPC 0x2F #define APIC_VECTOR_CMCI 0x35 #define APIC_VECTOR_SPURIOUS 0x3F #define APIC_VECTOR_REBOOT 0x50 #define APIC_VECTOR_GENERIC 0xC1 #define APIC_VECTOR_SYNC 0xD1 #define APIC_VECTOR_CLOCK 0xD1 #define APIC_VECTOR_CLOCK_IPI 0xD2 #define APIC_VECTOR_IPI 0xE1 #define APIC_VECTOR_ERROR 0xE3 #define APIC_VECTOR_POWERFAIL 0xEF #define APIC_VECTOR_PROFILE 0xFD #define APIC_VECTOR_PERF 0xFE #define APIC_VECTOR_NMI 0xFF /* APIC destination formats */ #define APIC_DF_FLAT 0xFFFFFFFF #define APIC_DF_CLUSTER 0x0FFFFFFF /* APIC trigger modes */ #define APIC_TGM_EDGE 0 #define APIC_TGM_LEVEL 1 /* APIC LDR (Logical Destination Register) shifts */ #define APIC_X2APIC_LDR_SHIFT 16 #define APIC_XAPIC_LDR_SHIFT 24 /* Maximum number of I/O APICs */ #define APIC_MAX_IOAPICS 64 /* I/O APIC base address */ #define IOAPIC_DEFAULT_BASE 0xFEC00000 /* I/O APIC definitions */ #define IOAPIC_MAX_CONTROLLERS 128 #define IOAPIC_MAX_OVERRIDES 16 #define IOAPIC_RTE_MASKED 0x100FF #define IOAPIC_RTE_SIZE 2 #define IOAPIC_VECTOR_FREE 0xFF #define IOAPIC_VECTOR_RESERVED 0xFE /* IOAPIC offsets */ #define IOAPIC_IOREGSEL 0x00 #define IOAPIC_IOWIN 0x10 /* IOAPIC registers */ #define IOAPIC_ID 0x00 #define IOAPIC_VER 0x01 #define IOAPIC_ARB 0x02 #define IOAPIC_REDTBL 0x10 /* 8259/ISP PIC ports definitions */ #define PIC1_CONTROL_PORT 0x20 #define PIC1_DATA_PORT 0x21 #define PIC2_CONTROL_PORT 0xA0 #define PIC2_DATA_PORT 0xA1 /* PIC vector definitions */ #define PIC1_VECTOR_SPURIOUS 0x37 /* HPET General Capabilities definitions */ #define HPET_CAPABILITY_64BIT 0x2000ULL #define HPET_CAPABILITY_LEGACY_REPLACEMENT 0x8000ULL /* HPET General Configuration definitions */ #define HPET_CONFIG_ENABLE 0x0001ULL #define HPET_CONFIG_LEGACY_REPLACEMENT 0x0002ULL /* HPET Timer Configuration definitions */ #define HPET_TIMER_CONFIG_LEVEL_TRIGGERED 0x0002ULL #define HPET_TIMER_CONFIG_ENABLED 0x0004ULL #define HPET_TIMER_CONFIG_PERIODIC 0x0008ULL #define HPET_TIMER_CONFIG_SUPPORTS_PERIODIC 0x0010ULL #define HPET_TIMER_CONFIG_SUPPORTS_64BIT 0x0020ULL #define HPET_TIMER_CONFIG_VALUE_ACCUMULATOR 0x0040ULL #define HPET_TIMER_CONFIG_FORCE_32BIT 0x0100ULL #define HPET_TIMER_CONFIG_FSB_ENABLED 0x4000ULL #define HPET_TIMER_CONFIG_SUPPORTS_FSB 0x8000ULL /* PIT ports definitions */ #define PIT_COMMAND_PORT 0x43 #define PIT_DATA_PORT0 0x40 #define PIT_DATA_PORT1 0x41 #define PIT_DATA_PORT2 0x42 /* PIT related definitions */ #define PIT_BASE_FREQUENCY 1193182 /* PIT Access Mode: Defines how the CPU reads or writes the counter value */ #define PIT_CMD_ACCESS_LATCH 0x00 #define PIT_CMD_ACCESS_LOWBYTE_ONLY 0x10 #define PIT_CMD_ACCESS_HIGHBYTE_ONLY 0x20 #define PIT_CMD_ACCESS_LOWBYTE_HIGHBYTE 0x30 /* PIT Channel Selection: Specifies the physical timer channel to configure */ #define PIT_CMD_CHANNEL0 0x00 #define PIT_CMD_CHANNEL1 0x40 #define PIT_CMD_CHANNEL2 0x80 /* PIT Operating Mode: Defines the hardware behavior and the generated waveform */ #define PIT_MODE0_INT_ON_TERMINAL_COUNT 0x00 #define PIT_MODE1_ONESHOT 0x02 #define PIT_MODE2_RATE_GENERATOR 0x04 #define PIT_MODE3_SQUARE_WAVE_GEN 0x06 #define PIT_MODE4_SOFTWARE_STROBE 0x08 #define PIT_MODE5_HARDWARE_STROBE 0x0A /* CMOS controller access ports */ #define CMOS_SELECT_PORT 0x70 #define CMOS_DATA_PORT 0x71 /* CMOD Select port definitions */ #define CMOS_NMI_SELECT 0x80 #define CMOS_REGISTER_SECOND 0x00 #define CMOS_REGISTER_MINUTE 0x02 #define CMOS_REGISTER_HOUR 0x04 #define CMOS_REGISTER_WEEKDAY 0x06 #define CMOS_REGISTER_DAY 0x07 #define CMOS_REGISTER_MONTH 0x08 #define CMOS_REGISTER_YEAR 0x09 #define CMOS_REGISTER_A 0x0A #define CMOS_REGISTER_B 0x0B #define CMOS_REGISTER_C 0x0C /* CMOS Register A definitions */ #define CMOS_REGISTER_A_RATE_MASK 0x0F #define CMOS_REGISTER_A_UPDATE_IN_PROGRESS 0x80 /* CMOS Register B definitions */ #define CMOS_REGISTER_B_24_HOUR 0x02 #define CMOS_REGISTER_B_BINARY 0x04 #define CMOS_REGISTER_B_PERIODIC 0x40 #define CMOS_REGISTER_B_SET_CLOCK 0x80 /* CMOS Register C definitions */ #define CMOS_REGISTER_C_PERIODIC 0x40 #define CMOS_REGISTER_C_INTERRUPT 0x80 /* CMOS RTC 24-hour mode */ #define CMOS_RTC_POST_MERIDIEM 0x80 /* Serial ports information */ #define COMPORT_ADDRESS {0x3F8, 0x2F8, 0x3E8, 0x2E8, 0x5F8, 0x4F8, 0x5E8, 0x4E8} #define COMPORT_COUNT 8 /* Initial stall factor */ #define INITIAL_STALL_FACTOR 100 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* APIC destination mode enumeration list */ typedef enum _APIC_DEST_MODE { APIC_DM_Physical, APIC_DM_Logical } APIC_DEST_MODE, *PAPIC_DEST_MODE; /* APIC delivery mode enumeration list */ typedef enum _APIC_DM { APIC_DM_FIXED, APIC_DM_LOWPRIO, APIC_DM_SMI, APIC_DM_REMOTE, APIC_DM_NMI, APIC_DM_INIT, APIC_DM_STARTUP, APIC_DM_EXTINT, } APIC_DM, *PAPIC_DM; /* APIC destination short-hand enumeration list */ typedef enum _APIC_DSH { APIC_DSH_Destination, APIC_DSH_Self, APIC_DSH_AllIncludingSelf, APIC_DSH_AllExclusingSelf } APIC_DSH, *PAPIC_DSH; /* APIC mode list */ typedef enum _APIC_MODE { APIC_MODE_COMPAT, APIC_MODE_X2APIC } APIC_MODE, *PAPIC_MODE; /* APIC Register Address Map */ typedef enum _APIC_REGISTER { APIC_ID = 0x02, /* APIC ID Register */ APIC_VER = 0x03, /* APIC Version Register */ APIC_TPR = 0x08, /* Task Priority Register */ APIC_APR = 0x09, /* Arbitration Priority Register */ APIC_PPR = 0x0A, /* Processor Priority Register (R) */ APIC_EOI = 0x0B, /* EOI Register */ APIC_RRR = 0x0C, /* Remote Read Register */ APIC_LDR = 0x0D, /* Logical Destination Register */ APIC_DFR = 0x0E, /* Destination Format Register (not available in extended mode) */ APIC_SIVR = 0x0F, /* Spurious Interrupt Vector Register */ APIC_ISR = 0x10, /* Interrupt Service Register*/ APIC_TMR = 0x18, /* Trigger Mode Register */ APIC_IRR = 0x20, /* Interrupt Request Register */ APIC_ESR = 0x28, /* Error Status Register */ APIC_ICR0 = 0x30, /* Interrupt Command Register */ APIC_ICR1 = 0x31, /* Interrupt Command Register (not available in extended mode) */ APIC_TMRLVTR = 0x32, /* Timer Local Vector Table */ APIC_THRMLVTR = 0x33, /* Thermal Local Vector Table */ APIC_PCLVTR = 0x34, /* Performance Counter Local Vector Table */ APIC_LINT0 = 0x35, /* LINT0 Local Vector Table */ APIC_LINT1 = 0x36, /* LINT1 Local Vector Table */ APIC_ERRLVTR = 0x37, /* Error Local Vector Table */ APIC_TICR = 0x38, /* Initial Count Register for Timer */ APIC_TCCR = 0x39, /* Current Count Register for Timer */ APIC_TDCR = 0x3E, /* Timer Divide Configuration Register */ APIC_SIPI = 0x3F, /* Self-IPI Register */ APIC_EAFR = 0x40, /* extended APIC Feature register */ APIC_EACR = 0x41, /* Extended APIC Control Register */ APIC_SEOI = 0x42, /* Specific End Of Interrupt Register */ APIC_EXT0LVTR = 0x50, /* Extended Interrupt 0 Local Vector Table */ APIC_EXT1LVTR = 0x51, /* Extended Interrupt 1 Local Vector Table */ APIC_EXT2LVTR = 0x52, /* Extended Interrupt 2 Local Vector Table */ APIC_EXT3LVTR = 0x53 /* Extended Interrupt 3 Local Vector Table */ } APIC_REGISTER, *PAPIC_REGISTER; /* APIC Timer Divide enumeration list */ typedef enum _APIC_TIMER_DIVISOR { TIMER_DivideBy2 = 0, TIMER_DivideBy4 = 1, TIMER_DivideBy8 = 2, TIMER_DivideBy16 = 3, TIMER_DivideBy32 = 8, TIMER_DivideBy64 = 9, TIMER_DivideBy128 = 10, TIMER_DivideBy1 = 11, } APIC_TIMER_DIVISOR, *PAPIC_TIMER_DIVISOR; /* I8259 PIC interrupt mode enumeration list */ typedef enum _PIC_I8259_ICW1_INTERRUPT_MODE { EdgeTriggered, LevelTriggered } PIC_I8259_ICW1_INTERRUPT_MODE, *PPIC_I8259_ICW1_INTERRUPT_MODE; /* I8259 PIC interval enumeration list */ typedef enum _PIC_I8259_ICW1_INTERVAL { Interval8, Interval4 } PIC_I8259_ICW1_INTERVAL, *PPIC_I8259_ICW1_INTERVAL; /* I8259 PIC operating mode enumeration list */ typedef enum _PIC_I8259_ICW1_OPERATING_MODE { Cascade, Single } PIC_I8259_ICW1_OPERATING_MODE, *PPIC_I8259_ICW1_OPERATING_MODE; /* I8259 PIC buffered mode enumeration list */ typedef enum _PIC_I8259_ICW4_BUFFERED_MODE { NonBuffered, NonBuffered2, BufferedSlave, BufferedMaster } PIC_I8259_ICW4_BUFFERED_MODE, *PPIC_I8259_ICW4_BUFFERED_MODE; /* I8259 PIC End Of Interrupt (EOI) mode enumeration list */ typedef enum _PIC_I8259_ICW4_EOI_MODE { NormalEoi, AutomaticEoi } PIC_I8259_ICW4_EOI_MODE, *PPIC_I8259_ICW4_EOI_MODE; /* I8259 PIC system mode enumeration list */ typedef enum _PIC_I8259_ICW4_SYSTEM_MODE { Mcs8085Mode, New8086Mode } PIC_I8259_ICW4_SYSTEM_MODE, *PPIC_I8259_ICW4_SYSTEM_MODE; /* Supported hardware timer backends */ typedef enum _TIMER_TYPE { TimerNone, TimerAcpiPm, TimerHpet, TimerLapic, TimerPit, TimerTsc } TIMER_TYPE, *PTIMER_TYPE; /* APIC Base Register */ typedef union _APIC_BASE_REGISTER { ULONGLONG LongLong; struct { ULONGLONG Reserved1:8; ULONGLONG BootStrapProcessor:1; ULONGLONG Reserved2:1; ULONGLONG ExtendedMode:1; ULONGLONG Enable:1; ULONGLONG BaseAddress:40; ULONGLONG Reserved3:12; }; } APIC_BASE_REGISTER, *PAPIC_BASE_REGISTER; /* APIC Command Register */ typedef union _APIC_COMMAND_REGISTER { ULONGLONG LongLong; struct { ULONG Long0; ULONG Long1; }; struct { ULONGLONG Vector:8; ULONGLONG DeliveryMode:3; ULONGLONG DestinationMode:1; ULONGLONG DeliveryStatus:1; ULONGLONG ReservedMBZ:1; ULONGLONG Level:1; ULONGLONG TriggerMode:1; ULONGLONG RemoteReadStatus:2; ULONGLONG DestinationShortHand:2; ULONGLONG Reserved2MBZ:36; ULONGLONG Destination:8; }; } APIC_COMMAND_REGISTER, *PAPIC_COMMAND_REGISTER; /* APIC Local Vector Table (LVT) Register */ typedef union _APIC_LVT_REGISTER { ULONG Long; struct { ULONG Vector:8; ULONG DeliveryMode:3; ULONG Reserved1:1; ULONG DeliveryStatus:1; ULONG Reserved2:1; ULONG RemoteIRR:1; ULONG TriggerMode:1; ULONG Mask:1; ULONG TimerMode:1; ULONG Reserved3:13; }; } APIC_LVT_REGISTER, *PAPIC_LVT_REGISTER; /* APIC Spurious Register */ typedef union _APIC_SPURIOUS_REGISTER { ULONG Long; struct { ULONG Vector:8; ULONG SoftwareEnable:1; ULONG CoreChecking:1; ULONG Reserved:22; }; } APIC_SPURIOUS_REGISTER, *PAPIC_SPURIOUS_REGISTER; /* I/O APIC Controller information */ typedef struct _IOAPIC_DATA { ULONG GsiBase; ULONG Identifier; ULONG LineCount; PHYSICAL_ADDRESS PhysicalAddress; ULONG_PTR VirtualAddress; } IOAPIC_DATA, *PIOAPIC_DATA; /* I/O APIC Redirection Register */ typedef union _IOAPIC_REDIRECTION_REGISTER { ULONGLONG LongLong; struct { UINT Base; UINT Extended; }; struct { ULONGLONG Vector:8; ULONGLONG DeliveryMode:3; ULONGLONG DestinationMode:1; ULONGLONG DeliveryStatus:1; ULONGLONG PinPolarity:1; ULONGLONG RemoteIRR:1; ULONGLONG TriggerMode:1; ULONGLONG Mask:1; ULONGLONG Reserved:39; ULONGLONG Destination:8; }; } IOAPIC_REDIRECTION_REGISTER, *PIOAPIC_REDIRECTION_REGISTER; /* I8259 PIC register structure */ typedef union _PIC_I8259_ICW1 { struct { UCHAR NeedIcw4:1; UCHAR OperatingMode:1; UCHAR Interval:1; UCHAR InterruptMode:1; UCHAR Init:1; UCHAR InterruptVectorAddress:3; }; UCHAR Bits; } PIC_I8259_ICW1, *PPIC_I8259_ICW1; /* I8259 PIC register structure */ typedef union _PIC_I8259_ICW2 { struct { UCHAR Sbz:3; UCHAR InterruptVector:5; }; UCHAR Bits; } PIC_I8259_ICW2, *PPIC_I8259_ICW2; /* I8259 PIC register structure */ typedef union _PIC_I8259_ICW3 { union { struct { UCHAR SlaveIrq0:1; UCHAR SlaveIrq1:1; UCHAR SlaveIrq2:1; UCHAR SlaveIrq3:1; UCHAR SlaveIrq4:1; UCHAR SlaveIrq5:1; UCHAR SlaveIrq6:1; UCHAR SlaveIrq7:1; }; struct { UCHAR SlaveId:3; UCHAR Reserved:5; }; }; UCHAR Bits; } PIC_I8259_ICW3, *PPIC_I8259_ICW3; /* I8259 PIC register structure */ typedef union _PIC_I8259_ICW4 { struct { UCHAR SystemMode:1; UCHAR EoiMode:1; UCHAR BufferedMode:2; UCHAR SpecialFullyNestedMode:1; UCHAR Reserved:3; }; UCHAR Bits; } PIC_I8259_ICW4, *PPIC_I8259_ICW4; /* HPET Registers structure definition */ typedef struct _HPET_REGISTERS { VOLATILE ULONGLONG GeneralCapabilities; VOLATILE ULONGLONG Reserved0; VOLATILE ULONGLONG GeneralConfiguration; VOLATILE ULONGLONG Reserved1; VOLATILE ULONGLONG GeneralInterruptStatus; VOLATILE ULONGLONG Reserved2; VOLATILE ULONGLONG Reserved3[2][12]; VOLATILE ULONGLONG MainCounterValue; VOLATILE ULONGLONG Reserved4; struct { VOLATILE ULONGLONG Configuration; VOLATILE ULONGLONG Comparator; VOLATILE ULONGLONG FsbInterruptRoute; VOLATILE ULONGLONG Reserved; } Timers[]; } HPET_REGISTERS, *PHPET_REGISTERS; /* Hardware timer capabilities and CPU clock features */ typedef struct _TIMER_CAPABILITIES { BOOLEAN Arat; BOOLEAN Art; BOOLEAN InvariantTsc; BOOLEAN RDTSCP; ULONG TimerFrequency; BOOLEAN TscDeadline; ULONG TscDenominator; ULONG TscNumerator; } TIMER_CAPABILITIES, *PTIMER_CAPABILITIES; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_AMD64_HLTYPES_H */ ================================================ FILE: sdk/xtdk/amd64/ketypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/amd64/ketypes.h * DESCRIPTION: Kernel services related structures definitions specific to AMD64 architecture * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_AMD64_KETYPES_H #define __XTDK_AMD64_KETYPES_H #include #include #include #include #include ARCH_HEADER(xtstruct.h) #include ARCH_HEADER(artypes.h) /* Selector masks */ #define MODE_MASK 0x0001 #define RPL_MASK 0x0003 /* GDT selector names */ #define KGDT_NULL 0x0000 #define KGDT_R0_CMCODE 0x0008 #define KGDT_R0_CODE 0x0010 #define KGDT_R0_DATA 0x0018 #define KGDT_R3_CMCODE 0x0020 #define KGDT_R3_DATA 0x0028 #define KGDT_R3_CODE 0x0030 #define KGDT_SYS_TSS 0x0040 #define KGDT_R3_CMTEB 0x0050 #define KGDT_R0_LDT 0x0060 #define KGDT_ALIAS 0x0070 /* GDT descriptor privilege levels */ #define KGDT_DPL_SYSTEM 0 #define KGDT_DPL_USER 3 /* GDT descriptor properties */ #define KGDT_DESCRIPTOR_ACCESSED 0x01 #define KGDT_DESCRIPTOR_READ_WRITE 0x02 #define KGDT_DESCRIPTOR_EXECUTE_READ 0x02 #define KGDT_DESCRIPTOR_EXPAND_DOWN 0x04 #define KGDT_DESCRIPTOR_CONFORMING 0x04 #define KGDT_DESCRIPTOR_CODE 0x08 /* GDT descriptor type codes */ #define KGDT_TYPE_NONE 0x00 #define KGDT_TYPE_CODE (0x10 | KGDT_DESCRIPTOR_CODE | KGDT_DESCRIPTOR_EXECUTE_READ) #define KGDT_TYPE_DATA (0x10 | KGDT_DESCRIPTOR_READ_WRITE) /* IDT access levels */ #define KIDT_ACCESS_RING0 0x0 #define KIDT_ACCESS_RING3 0x3 /* IDT Interrupt Stack Table entries */ #define KIDT_IST_RESERVED 0 #define KIDT_IST_PANIC 1 #define KIDT_IST_MCA 2 #define KIDT_IST_NMI 3 /* AMD64 Segment Types */ #define AMD64_TASK_GATE 0x5 #define AMD64_TSS 0x9 #define AMD64_ACTIVE_TSS 0xB #define AMD64_CALL_GATE 0xC #define AMD64_INTERRUPT_GATE 0xE #define AMD64_TRAP_GATE 0xF /* Kernel CPU Standard Features */ #define KCF_VME (1ULL << 0) /* Virtual 8086 Mode Enhancements */ #define KCF_LARGE_PAGE (1ULL << 1) /* Page Size Extensions */ #define KCF_RDTSC (1ULL << 2) /* Time Stamp Counter */ #define KCF_PAE (1ULL << 3) /* Physical Address Extension */ #define KCF_MCE (1ULL << 4) /* Machine Check Exception */ #define KCF_CMPXCHG8B (1ULL << 5) /* CMPXCHG8B Instruction */ #define KCF_APIC (1ULL << 6) /* APIC On-Chip */ #define KCF_FAST_SYSCALL (1ULL << 7) /* SYSENTER/SYSEXIT Instructions */ #define KCF_MTRR (1ULL << 8) /* Memory Type Range Registers */ #define KCF_GLOBAL_PAGE (1ULL << 9) /* Page Global Enable */ #define KCF_MCA (1ULL << 10) /* Machine Check Architecture */ #define KCF_CMOV (1ULL << 11) /* Conditional Move Instructions */ #define KCF_PAT (1ULL << 12) /* Page Attribute Table */ #define KCF_PSE36 (1ULL << 13) /* 36-bit Page Size Extension */ #define KCF_CLFLUSH (1ULL << 14) /* CLFLUSH Instruction */ #define KCF_FXSR (1ULL << 15) /* FXSAVE/FXRSTOR Instructions */ #define KCF_ACPI (1ULL << 16) /* Thermal Monitor and Software Controlled Clock */ #define KCF_MMX (1ULL << 17) /* MMX Technology */ #define KCF_SSE (1ULL << 18) /* Streaming SIMD Extensions */ #define KCF_SSE2 (1ULL << 19) /* Streaming SIMD Extensions 2 */ #define KCF_SMT (1ULL << 20) /* Hyper-Threading Technology */ #define KCF_SSE3 (1ULL << 21) /* Streaming SIMD Extensions 3 */ #define KCF_VMX (1ULL << 22) /* Intel Virtual Machine Extensions */ #define KCF_SSSE3 (1ULL << 23) /* Supplemental SSE3 Instructions */ #define KCF_SSE41 (1ULL << 24) /* SSE4.1 Instructions */ #define KCF_SSE42 (1ULL << 25) /* SSE4.2 Instructions */ #define KCF_X2APIC (1ULL << 26) /* x2APIC Support */ #define KCF_POPCNT (1ULL << 27) /* POPCNT Instruction */ #define KCF_TSC_DEADLINE (1ULL << 28) /* TSC Deadline Timer */ #define KCF_AES (1ULL << 29) /* AES-NI Instruction Set */ #define KCF_XSAVE (1ULL << 30) /* XSAVE/XRSTOR Instructions */ #define KCF_AVX (1ULL << 31) /* Advanced Vector Extensions */ #define KCF_RDRAND (1ULL << 32) /* RDRAND Instruction */ #define KCF_FSGSBASE (1ULL << 33) /* RDFSBASE/WRFSBASE Instructions */ #define KCF_AVX2 (1ULL << 34) /* AVX2 Instructions */ #define KCF_SMEP (1ULL << 35) /* Supervisor Mode Execution Prevention */ #define KCF_RDSEED (1ULL << 36) /* RDSEED Instruction */ #define KCF_SMAP (1ULL << 37) /* Supervisor Mode Access Prevention */ #define KCF_SHA (1ULL << 38) /* SHA Extensions */ #define KCF_LA57 (1ULL << 39) /* 57-bit Linear Addresses */ #define KCF_ARAT (1ULL << 40) /* Always Running APIC Timer */ /* Kernel CPU Extended Features */ #define KCF_SVM (1ULL << 0) /* AMD Secure Virtual Machine */ #define KCF_SSE4A (1ULL << 1) /* SSE4A Instructions */ #define KCF_FMA4 (1ULL << 2) /* FMA4 Instructions */ #define KCF_TOPOEXT (1ULL << 3) /* AMD Topology Extensions */ #define KCF_SYSCALL (1ULL << 4) /* SYSCALL/SYSRET Instructions */ #define KCF_NX_BIT (1ULL << 5) /* No-Execute Page Protection */ #define KCF_RDTSCP (1ULL << 6) /* RDTSCP Instruction */ #define KCF_64BIT (1ULL << 7) /* Long Mode Support */ #define KCF_3DNOW_EXT (1ULL << 8) /* 3DNow! Extensions */ #define KCF_3DNOW (1ULL << 9) /* 3DNow! Instructions */ #define KCF_INVARIANT_TSC (1ULL << 10) /* Invariant Time Stamp Counter */ /* Context control flags */ #define CONTEXT_ARCHITECTURE 0x00100000 #define CONTEXT_CONTROL (CONTEXT_ARCHITECTURE | 0x01) #define CONTEXT_INTEGER (CONTEXT_ARCHITECTURE | 0x02) #define CONTEXT_SEGMENTS (CONTEXT_ARCHITECTURE | 0x04) #define CONTEXT_FLOATING_POINT (CONTEXT_ARCHITECTURE | 0x08) #define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARCHITECTURE | 0x10) /* Interrupt request levels definitions */ #define PASSIVE_LEVEL 0 #define LOW_LEVEL 0 #define APC_LEVEL 1 #define DISPATCH_LEVEL 2 #define CMC_LEVEL 5 #define DEVICE1_LEVEL 6 #define DEVICE2_LEVEL 7 #define DEVICE3_LEVEL 8 #define DEVICE4_LEVEL 9 #define DEVICE5_LEVEL 10 #define DEVICE6_LEVEL 11 #define DEVICE7_LEVEL 12 #define SYNC_LEVEL 12 #define CLOCK_LEVEL 13 #define IPI_LEVEL 14 #define DRS_LEVEL 14 #define POWER_LEVEL 14 #define PROFILE_LEVEL 15 #define HIGH_LEVEL 15 /* Size of the exception area */ #define EXCEPTION_AREA_SIZE 64 /* IOPM Definitions */ #define IO_ACCESS_MAP_NONE 0 /* Size of the FNSAVE/FRSTOR save area */ #define FLOATING_SAVE_AREA_SIZE ((sizeof(FLOATING_SAVE_AREA) + 15) & ~15) /* Static Kernel-Mode address start */ #define KSEG0_BASE 0xFFFFF80000000000 /* XTOS Kernel stack size */ #define KERNEL_STACK_SIZE 0x8000 #define KERNEL_STACKS 3 /* XTOS Kernel stack guard pages */ #define KERNEL_STACK_GUARD_PAGES 1 /* Processor structures size */ #define KPROCESSOR_STRUCTURES_SIZE ((KERNEL_STACKS * KERNEL_STACK_SIZE) + (GDT_ENTRIES * sizeof(KGDTENTRY)) + \ sizeof(KTSS) + sizeof(KPROCESSOR_BLOCK) + MM_PAGE_SIZE) /* Kernel frames */ #define KEXCEPTION_FRAME_SIZE sizeof(KEXCEPTION_FRAME) #define KSWITCH_FRAME_SIZE sizeof(KSWITCH_FRAME) #define KTRAP_FRAME_ALIGN 0x10 #define KTRAP_FRAME_SIZE sizeof(KTRAP_FRAME) /* Return address size pushed by 'call' instruction */ #define KRETURN_ADDRESS_SIZE 0x8 /* Size of legacy 387 registers */ #define SIZE_OF_80387_REGISTERS 80 /* NPX state definitions */ #define NPX_STATE_UNUSED 0x0 #define NPX_STATE_SCRUB 0x1 #define NPX_STATE_SWITCH 0x2 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Floating point state storing structure */ typedef struct _FLOATING_SAVE_AREA { USHORT ControlWord; USHORT StatusWord; USHORT TagWord; ULONG ErrorOffset; USHORT ErrorSelector; USHORT ErrorOpcode; ULONG DataOffset; USHORT DataSelector; UCHAR RegisterArea[SIZE_OF_80387_REGISTERS]; } FLOATING_SAVE_AREA, *PFLOATING_SAVE_AREA; /* Context frame structure definition */ typedef struct _CONTEXT { ULONG64 P1Home; ULONG64 P2Home; ULONG64 P3Home; ULONG64 P4Home; ULONG64 P5Home; ULONG64 P6Home; ULONG ContextFlags; ULONG MxCsr; USHORT SegCs; USHORT SegDs; USHORT SegEs; USHORT SegFs; USHORT SegGs; USHORT SegSs; ULONG EFlags; ULONG64 Dr0; ULONG64 Dr1; ULONG64 Dr2; ULONG64 Dr3; ULONG64 Dr6; ULONG64 Dr7; ULONG64 Rax; ULONG64 Rcx; ULONG64 Rdx; ULONG64 Rbx; ULONG64 Rsp; ULONG64 Rbp; ULONG64 Rsi; ULONG64 Rdi; ULONG64 R8; ULONG64 R9; ULONG64 R10; ULONG64 R11; ULONG64 R12; ULONG64 R13; ULONG64 R14; ULONG64 R15; ULONG64 Rip; union { FLOATING_SAVE_AREA FloatSave; struct { M128 Header[2]; M128 Legacy[8]; M128 Xmm0; M128 Xmm1; M128 Xmm2; M128 Xmm3; M128 Xmm4; M128 Xmm5; M128 Xmm6; M128 Xmm7; M128 Xmm8; M128 Xmm9; M128 Xmm10; M128 Xmm11; M128 Xmm12; M128 Xmm13; M128 Xmm14; M128 Xmm15; }; }; M128 VectorRegister[26]; ULONG64 VectorControl; ULONG64 DebugControl; ULONG64 LastBranchToRip; ULONG64 LastBranchFromRip; ULONG64 LastExceptionToRip; ULONG64 LastExceptionFromRip; } ALIGN(16) CONTEXT, *PCONTEXT; /* Pseudo 64-bit descriptor structure definition */ typedef struct _KDESCRIPTOR { USHORT Pad[3]; USHORT Limit; PVOID Base; } KDESCRIPTOR, *PKDESCRIPTOR; /* Global Descriptor Table (GDT) entry union definition */ typedef struct _KGDTENTRY { USHORT LimitLow; USHORT BaseLow; union { struct { UCHAR BaseMiddle; UCHAR Flags1; UCHAR Flags2; UCHAR BaseHigh; } Bytes; struct { ULONG BaseMiddle:8; ULONG Type:5; ULONG Dpl:2; ULONG Present:1; ULONG LimitHigh:4; ULONG System:1; ULONG LongMode:1; ULONG DefaultBig:1; ULONG Granularity:1; ULONG BaseHigh:8; } Bits; }; ULONG BaseUpper; ULONG MustBeZero; } KGDTENTRY, *PKGDTENTRY; /* Interrupt Descriptor Table (IDT) entry union definition */ typedef struct _KIDTENTRY { USHORT OffsetLow; USHORT Selector; union { struct { USHORT IstIndex:3; USHORT Reserved0:5; USHORT Type:5; USHORT Dpl:2; USHORT Present:1; }; USHORT Access; }; USHORT OffsetMiddle; ULONG OffsetHigh; ULONG Reserved1; } KIDTENTRY, *PKIDTENTRY; /* Task State Segment (TSS) structure definition */ typedef struct _KTSS { ULONG Reserved0; ULONG64 Rsp0; ULONG64 Rsp1; ULONG64 Rsp2; ULONG64 Ist[8]; ULONG64 Reserved1; USHORT Reserved2; USHORT IoMapBase; } PACKED KTSS, *PKTSS; /* Exception frame definition */ typedef struct _KEXCEPTION_FRAME { ULONG64 P1Home; ULONG64 P2Home; ULONG64 P3Home; ULONG64 P4Home; ULONG64 P5; ULONG64 InitialStack; M128 Xmm6; M128 Xmm7; M128 Xmm8; M128 Xmm9; M128 Xmm10; M128 Xmm11; M128 Xmm12; M128 Xmm13; M128 Xmm14; M128 Xmm15; ULONG64 TrapFrame; ULONG64 CallbackStack; ULONG64 OutputBuffer; ULONG64 OutputLength; UCHAR ExceptionRecord[EXCEPTION_AREA_SIZE]; ULONG64 MxCsr; ULONG64 Rbp; ULONG64 Rbx; ULONG64 Rdi; ULONG64 Rsi; ULONG64 R12; ULONG64 R13; ULONG64 R14; ULONG64 R15; ULONG64 Return; } KEXCEPTION_FRAME, *PKEXCEPTION_FRAME; /* Thread start frame definition */ typedef struct _KSTART_FRAME { ULONG64 P1Home; ULONG64 P2Home; ULONG64 P3Home; ULONG64 P4Home; ULONG64 Reserved; ULONG64 Return; } KSTART_FRAME, *PKSTART_FRAME; /* Switch frame definition */ typedef struct _KSWITCH_FRAME { ULONG64 P1Home; ULONG64 P2Home; ULONG64 P3Home; ULONG64 P4Home; ULONG64 P5Home; ULONG MxCsr; KRUNLEVEL ApcBypass; UCHAR Reserved[3]; ULONG64 Rbp; ULONG64 Return; } KSWITCH_FRAME, *PKSWITCH_FRAME; /* Trap frame definition */ typedef struct _KTRAP_FRAME { M128 Xmm0; M128 Xmm1; M128 Xmm2; M128 Xmm3; M128 Xmm4; M128 Xmm5; M128 Xmm6; M128 Xmm7; M128 Xmm8; M128 Xmm9; M128 Xmm10; M128 Xmm11; M128 Xmm12; M128 Xmm13; M128 Xmm14; M128 Xmm15; ULONG MxCsr; ULONG PreviousMode; ULONGLONG Cr2; ULONGLONG Cr3; ULONGLONG Dr0; ULONGLONG Dr1; ULONGLONG Dr2; ULONGLONG Dr3; ULONGLONG Dr6; ULONGLONG Dr7; USHORT SegDs; USHORT SegEs; USHORT SegFs; USHORT SegGs; ULONGLONG Rax; ULONGLONG Rbx; ULONGLONG Rcx; ULONGLONG Rdx; ULONGLONG R8; ULONGLONG R9; ULONGLONG R10; ULONGLONG R11; ULONGLONG R12; ULONGLONG R13; ULONGLONG R14; ULONGLONG R15; ULONGLONG Rsi; ULONGLONG Rdi; ULONGLONG Rbp; ULONGLONG Vector; union { ULONGLONG ErrorCode; ULONGLONG ExceptionFrame; }; ULONGLONG Rip; ULONGLONG SegCs; ULONGLONG Flags; ULONGLONG Rsp; ULONGLONG SegSs; } KTRAP_FRAME, *PKTRAP_FRAME; /* Thread initialization frame definition */ typedef struct _KTHREAD_INIT_FRAME { KSWITCH_FRAME SwitchFrame; KSTART_FRAME StartFrame; KEXCEPTION_FRAME ExceptionFrame; KTRAP_FRAME TrapFrame; FLOATING_SAVE_AREA NpxFrame; } KTHREAD_INIT_FRAME, *PKTHREAD_INIT_FRAME; /* Special kernel registers structure definition */ typedef struct _KSPECIAL_REGISTERS { ULONG64 Cr0; ULONG64 Cr2; ULONG64 Cr3; ULONG64 Cr4; ULONG64 KernelDr0; ULONG64 KernelDr1; ULONG64 KernelDr2; ULONG64 KernelDr3; ULONG64 KernelDr6; ULONG64 KernelDr7; KDESCRIPTOR Gdtr; KDESCRIPTOR Idtr; USHORT Tr; USHORT Ldtr; ULONG MxCsr; ULONG64 DebugControl; ULONG64 LastBranchToRip; ULONG64 LastBranchFromRip; ULONG64 LastExceptionToRip; ULONG64 LastExceptionFromRip; ULONG64 Cr8; ULONG64 MsrGsBase; ULONG64 MsrGsSwap; ULONG64 MsrStar; ULONG64 MsrLStar; ULONG64 MsrCStar; ULONG64 MsrSyscallMask; } KSPECIAL_REGISTERS, *PKSPECIAL_REGISTERS; /* Processor start block structure definition */ typedef struct _PROCESSOR_START_BLOCK { ULONG_PTR Cr3; ULONG_PTR Cr4; PVOID EntryPoint; PVOID ProcessorStructures; PVOID Stack; BOOLEAN Started; } PROCESSOR_START_BLOCK, *PPROCESSOR_START_BLOCK; /* Processor state frame structure definition */ typedef struct _KPROCESSOR_STATE { CONTEXT ContextFrame; KSPECIAL_REGISTERS SpecialRegisters; } KPROCESSOR_STATE, *PKPROCESSOR_STATE; /* Processor Control Block (PRCB) structure definition */ typedef struct _KPROCESSOR_CONTROL_BLOCK { ULONG MxCsr; UCHAR CpuNumber; PKTHREAD CurrentThread; PKTHREAD IdleThread; PKTHREAD NextThread; ULONG64 RspBase; ULONG_PTR SetMember; CPU_IDENTIFICATION CpuId; KPROCESSOR_STATE ProcessorState; KSPIN_LOCK_QUEUE LockQueue[MaximumLock]; KDPC_DATA DpcData[2]; PVOID DpcStack; VOLATILE BOOLEAN DpcRoutineActive; VOLATILE ULONG_PTR TimerRequest; ULONG_PTR MultiThreadProcessorSet; SINGLE_LIST_ENTRY DeferredReadyListHead; PROCESSOR_POWER_STATE PowerState; ULONG ProfilingCountdown; } KPROCESSOR_CONTROL_BLOCK, *PKPROCESSOR_CONTROL_BLOCK; /* Processor Block structure definition */ typedef struct _KPROCESSOR_BLOCK { union { THREAD_INFORMATION_BLOCK ThreadInformationBlock; struct { PKGDTENTRY GdtBase; PKTSS TssBase; PKPROCESSOR_BLOCK Self; PKPROCESSOR_CONTROL_BLOCK CurrentPrcb; }; }; PKIDTENTRY IdtBase; KRUNLEVEL RunLevel; KPROCESSOR_CONTROL_BLOCK Prcb; ULONG Irr; ULONG IrrActive; ULONG Idr; ULONG ContextSwitches; KAFFINITY SetMember; ULONG StallScaleFactor; UCHAR CpuNumber; ULONG HardwareId; VOLATILE BOOLEAN Started; PINTERRUPT_HANDLER InterruptDispatchTable[256]; } KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK; /* Thread Environment Block (TEB) structure definition */ typedef struct _THREAD_ENVIRONMENT_BLOCK { THREAD_INFORMATION_BLOCK InformationBlock; } THREAD_ENVIRONMENT_BLOCK, *PTHREAD_ENVIRONMENT_BLOCK; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_AMD64_KETYPES_H */ ================================================ FILE: sdk/xtdk/amd64/mmtypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/amd64/mmtypes.h * DESCRIPTION: Memory management data structures for AMD64 architecture * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_AMD64_MMTYPES_H #define __XTDK_AMD64_MMTYPES_H #include #include /* Pages related definitions */ #define MM_PAGE_MASK (MM_PAGE_SIZE - 1) #define MM_PAGE_SHIFT 12L #define MM_PAGE_SIZE 4096 /* Page directory and page base addresses for 4-level paging */ #define MM_PTE_BASE 0xFFFFF68000000000ULL #define MM_PDE_BASE 0xFFFFF6FB40000000ULL #define MM_PPE_BASE 0xFFFFF6FB7DA00000ULL #define MM_PXE_BASE 0xFFFFF6FB7DBED000ULL /* Page directory and page base addresses for 5-level paging */ #define MM_PTE_LA57_BASE 0xFFED000000000000ULL #define MM_PDE_LA57_BASE 0xFFEDF68000000000ULL #define MM_PPE_LA57_BASE 0xFFEDF6FB40000000ULL #define MM_PXE_LA57_BASE 0xFFEDF6FB7DA00000ULL #define MM_P5E_LA57_BASE 0xFFEDF6FB7DBED000ULL /* PTE shift values */ #define MM_PTE_SHIFT 3 #define MM_PTI_SHIFT 12 #define MM_PDI_SHIFT 21 #define MM_PPI_SHIFT 30 #define MM_PXI_SHIFT 39 #define MM_P5I_SHIFT 48 /* PTE state flags */ #define MM_PTE_VALID 0x0000000000000001ULL #define MM_PTE_ACCESSED 0x0000000000000020ULL #define MM_PTE_DIRTY 0x0000000000000040ULL /* PTE scope flags */ #define MM_PTE_LARGE_PAGE 0x0000000000000080ULL #define MM_PTE_GLOBAL 0x0000000000000100ULL /* PTE access flags */ #define MM_PTE_NOACCESS 0x0000000000000000ULL #define MM_PTE_READONLY 0x0000000000000000ULL #define MM_PTE_EXECUTE 0x0000000000000000ULL #define MM_PTE_EXECUTE_READ 0x0000000000000000ULL #define MM_PTE_READWRITE 0x8000000000000002ULL #define MM_PTE_WRITECOPY 0x8000000000000200ULL #define MM_PTE_EXECUTE_READWRITE 0x0000000000000002ULL #define MM_PTE_EXECUTE_WRITECOPY 0x0000000000000200ULL /* PTE protection flags */ #define MM_PTE_NOEXECUTE 0x8000000000000000ULL #define MM_PTE_GUARDED 0x8000000000000018ULL #define MM_PTE_PROTECT 0x8000000000000612ULL /* PTE cache flags */ #define MM_PTE_CACHE_ENABLE 0x0000000000000000ULL #define MM_PTE_CACHE_DISABLE 0x0000000000000010ULL #define MM_PTE_CACHE_WRITECOMBINED 0x0000000000000010ULL #define MM_PTE_CACHE_WRITETHROUGH 0x0000000000000008ULL /* PTE software flags */ #define MM_PTE_COPY_ON_WRITE 0x0000000000000200ULL #define MM_PTE_PROTOTYPE 0x0000000000000400ULL #define MM_PTE_TRANSITION 0x0000000000000800ULL /* PTE frame bits */ #define MM_PTE_FRAME_BITS 57 /* PTE protection bits */ #define MM_PTE_PROTECTION_BITS 5 /* Base address of the system page table */ #define MM_SYSTEM_PTE_BASE KSEG0_BASE /* Minimum number of physical pages needed by the system */ #define MM_MINIMUM_PHYSICAL_PAGES 2048 /* Number of system PTEs */ #define MM_DEFAULT_NUMBER_SYSTEM_PTES 22000 /* Default number of secondary colors */ #define MM_DEFAULT_SECONDARY_COLORS 64 /* Number of HAL allocation descriptors */ #define MM_HARDWARE_ALLOCATION_DESCRIPTORS 64 /* Kernel HAL heap initial start address */ #define MM_HARDWARE_HEAP_START_ADDRESS ((PVOID)(((ULONG_PTR)MM_HARDWARE_VA_START) + 1024 * 1024)) /* HAL memory pool virtual address start */ #define MM_HARDWARE_VA_START 0xFFFFFFFFFFC00000ULL /* Kernel shared data address */ #define MM_KERNEL_SHARED_DATA_ADDRESS 0xFFFFFFFFFFDF0000ULL /* Maximum physical address used by HAL allocations */ #define MM_MAXIMUM_PHYSICAL_ADDRESS 0x00000000FFFFFFFFULL /* Highest system address */ #define MM_HIGHEST_SYSTEM_ADDRESS 0xFFFFFFFFFFFFFFFFULL /* Trampoline code address */ #define MM_TRAMPOLINE_ADDRESS 0x80000 /* Pool block size */ #define MM_POOL_BLOCK_SIZE 16 /* Number of pool lists per page */ #define MM_POOL_LISTS_PER_PAGE (MM_PAGE_SIZE / MM_POOL_BLOCK_SIZE) /* Number of pool tracking tables */ #define MM_POOL_TRACKING_TABLES 64 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Page size enumeration list */ typedef enum _PAGE_SIZE { Size4K, Size2M, Size1G } PAGE_SIZE, *PPAGE_SIZE; /* Page Table Entry structure definition */ typedef struct _HARDWARE_PTE { ULONGLONG Valid:1; ULONGLONG Writable:1; ULONGLONG Owner:1; ULONGLONG WriteThrough:1; ULONGLONG CacheDisable:1; ULONGLONG Accessed:1; ULONGLONG Dirty:1; ULONGLONG LargePage:1; ULONGLONG Global:1; ULONGLONG CopyOnWrite:1; ULONGLONG Prototype:1; ULONGLONG Reserved1:1; ULONGLONG PageFrameNumber:36; ULONGLONG Reserved2:4; ULONGLONG SoftwareWsIndex:11; ULONGLONG NoExecute:1; } HARDWARE_PTE, *PHARDWARE_PTE; /* Page map information structure definition */ typedef struct _MMPAGEMAP_INFO { BOOLEAN Xpa; ULONGLONG PteBase; ULONGLONG PdeBase; ULONGLONG PpeBase; ULONGLONG PxeBase; ULONGLONG P5eBase; ULONG VaBits; } MMPAGEMAP_INFO, *PMMPAGEMAP_INFO; /* A Page Table Entry on AMD64 system */ typedef struct _MMPTE_HARDWARE { ULONGLONG Valid:1; ULONGLONG Writable:1; ULONGLONG Owner:1; ULONGLONG WriteThrough:1; ULONGLONG CacheDisable:1; ULONGLONG Accessed:1; ULONGLONG Dirty:1; ULONGLONG LargePage:1; ULONGLONG Global:1; ULONGLONG CopyOnWrite:1; ULONGLONG Prototype:1; ULONGLONG Write:1; ULONGLONG PageFrameNumber:36; ULONGLONG Reserved1:2; ULONGLONG SoftwareWsIndex:11; ULONGLONG NoExecute:1; } MMPTE_HARDWARE, *PMMPTE_HARDWARE; /* A Page Table Entry on AMD64 system with large pages */ typedef struct _MMPTE_HARDWARE_LARGEPAGE { ULONGLONG Valid:1; ULONGLONG Write:1; ULONGLONG Owner:1; ULONGLONG WriteThrough:1; ULONGLONG CacheDisable:1; ULONGLONG Accessed:1; ULONGLONG Dirty:1; ULONGLONG LargePage:1; ULONGLONG Global:1; ULONGLONG CopyOnWrite:1; ULONGLONG Prototype:1; ULONGLONG Reserved1:1; ULONGLONG PAT:1; ULONGLONG Reserved2:8; ULONGLONG PageFrameNumber:19; ULONGLONG Reserved3:24; } MMPTE_HARDWARE_LARGEPAGE, *PMMPTE_HARDWARE_LARGEPAGE; /* Page Table Entry list structure definition */ typedef struct _MMPTE_LIST { ULONGLONG Valid:1; ULONGLONG OneEntry:1; ULONGLONG Reserved1:3; ULONGLONG Protection:5; ULONGLONG Prototype:1; ULONGLONG Transition:1; ULONGLONG Reserved2:20; ULONGLONG NextEntry:32; } MMPTE_LIST, *PMMPTE_LIST; /* Page Table Entry prototype structure definition */ typedef struct _MMPTE_PROTOTYPE { ULONGLONG Valid:1; ULONGLONG Reserved1:7; ULONGLONG ReadOnly:1; ULONGLONG Reserved2:1; ULONGLONG Prototype:1; ULONGLONG Protection:5; LONGLONG ProtoAddress:48; } MMPTE_PROTOTYPE, *PMMPTE_PROTOTYPE; /* Software Page Table Entry structure definition */ typedef struct _MMPTE_SOFTWARE { ULONGLONG Valid:1; ULONGLONG PageFileLow:4; ULONGLONG Protection:5; ULONGLONG Prototype:1; ULONGLONG Transition:1; ULONGLONG UsedPageTableEntries:10; ULONGLONG Reserved:10; ULONGLONG PageFileHigh:32; } MMPTE_SOFTWARE, *PMMPTE_SOFTWARE; /* Page Table Entry subsection structure definition */ typedef struct _MMPTE_SUBSECTION { ULONGLONG Valid:1; ULONGLONG Reserved1:4; ULONGLONG Protection:5; ULONGLONG Prototype:1; ULONGLONG Reserved2:5; LONGLONG SubsectionAddress:48; } MMPTE_SUBSECTION, *PMMPTE_SUBSECTION; /* Page Table Entry transition structure definition */ typedef struct _MMPTE_TRANSITION { ULONGLONG Valid:1; ULONGLONG Write:1; ULONGLONG Owner:1; ULONGLONG WriteThrough:1; ULONGLONG CacheDisable:1; ULONGLONG Protection:5; ULONGLONG Prototype:1; ULONGLONG Transition:1; ULONGLONG PageFrameNumber:36; ULONGLONG Unused:16; } MMPTE_TRANSITION, *PMMPTE_TRANSITION; /* Page Table Entry structure definition */ typedef union _MMPTE { ULONGLONG Long; HARDWARE_PTE Flush; MMPTE_HARDWARE Hardware; MMPTE_PROTOTYPE Prototype; MMPTE_SOFTWARE Software; MMPTE_TRANSITION Transition; MMPTE_SUBSECTION Subsection; MMPTE_LIST List; } MMPTE, *PMMPTE; /* Page Frame Number structure definition */ typedef struct _MMPFN { union { PFN_NUMBER Flink; ULONG WsIndex; PKEVENT Event; XTSTATUS ReadStatus; SINGLE_LIST_ENTRY NextStackPfn; } u1; PMMPTE PteAddress; union { PFN_NUMBER Blink; ULONG_PTR ShareCount; } u2; union { MMPFNENTRY e1; struct { USHORT ShortFlags; USHORT ReferenceCount; } e2; } u3; ULONG UsedPageTableEntries; union { MMPTE OriginalPte; LONG AweReferenceCount; }; union { ULONG_PTR EntireFrame; struct { ULONG_PTR PteFrame:57; ULONG_PTR InPageError:1; ULONG_PTR VerifierAllocation:1; ULONG_PTR AweAllocation:1; ULONG_PTR Priority:3; ULONG_PTR MustBeCached:1; }; } u4; } MMPFN, *PMMPFN; /* Pool descriptor structure definition */ typedef struct _POOL_DESCRIPTOR { LIST_ENTRY ListHeads[MM_POOL_LISTS_PER_PAGE]; PVOID LockAddress; ULONG PoolIndex; LONG PendingFreeDepth; PVOID PendingFrees; MMPOOL_TYPE PoolType; ULONG RunningFrees; ULONG RunningAllocations; ULONG Threshold; ULONG TotalPages; ULONG TotalBigAllocations; SIZE_T TotalBytes; SIZE_T Reserved; } POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_AMD64_MMTYPES_H */ ================================================ FILE: sdk/xtdk/amd64/xtstruct.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/amd64/xtstruct.h * DESCRIPTION: XT structures forward references specific to AMD64 architecture * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_AMD64_XTSTRUCT_H #define __XTDK_AMD64_XTSTRUCT_H #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Architecture-specific enumeration lists forward references */ typedef enum _APIC_DEST_MODE APIC_DEST_MODE, *PAPIC_DEST_MODE; typedef enum _APIC_DM APIC_DM, *PAPIC_DM; typedef enum _APIC_DSH APIC_DSH, *PAPIC_DSH; typedef enum _APIC_MODE APIC_MODE, *PAPIC_MODE; typedef enum _APIC_REGISTER APIC_REGISTER, *PAPIC_REGISTER; typedef enum _APIC_TIMER_DIVISOR APIC_TIMER_DIVISOR, *PAPIC_TIMER_DIVISOR; typedef enum _CPU_VENDOR CPU_VENDOR, *PCPU_VENDOR; typedef enum _CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT, *PCPUID_FEATURES_ADVANCED_POWER_MANAGEMENT; typedef enum _CPUID_FEATURES_EXTENDED CPUID_FEATURES_EXTENDED, *PCPUID_FEATURES_EXTENDED; typedef enum _CPUID_FEATURES_POWER_MANAGEMENT CPUID_FEATURES_POWER_MANAGEMENT, *PCPUID_FEATURES_POWER_MANAGEMENT; typedef enum _CPUID_FEATURES_STANDARD1 CPUID_FEATURES_STANDARD1, *PCPUID_FEATURES_STANDARD1; typedef enum _CPUID_FEATURES_STANDARD7_LEAF0 CPUID_FEATURES_STANDARD7_LEAF0, *PCPUID_FEATURES_STANDARD7_LEAF0; typedef enum _CPUID_FEATURES_STANDARD7_LEAF1 CPUID_FEATURES_STANDARD7_LEAF1, *PCPUID_FEATURES_STANDARD7_LEAF1; typedef enum _CPUID_REQUESTS CPUID_REQUESTS, *PCPUID_REQUESTS; typedef enum _PAGE_SIZE PAGE_SIZE, *PPAGE_SIZE; typedef enum _PIC_I8259_ICW1_INTERRUPT_MODE PIC_I8259_ICW1_INTERRUPT_MODE, *PPIC_I8259_ICW1_INTERRUPT_MODE; typedef enum _PIC_I8259_ICW1_INTERVAL PIC_I8259_ICW1_INTERVAL, *PPIC_I8259_ICW1_INTERVAL; typedef enum _PIC_I8259_ICW1_OPERATING_MODE PIC_I8259_ICW1_OPERATING_MODE, *PPIC_I8259_ICW1_OPERATING_MODE; typedef enum _PIC_I8259_ICW4_BUFFERED_MODE PIC_I8259_ICW4_BUFFERED_MODE, *PPIC_I8259_ICW4_BUFFERED_MODE; typedef enum _PIC_I8259_ICW4_EOI_MODE PIC_I8259_ICW4_EOI_MODE, *PPIC_I8259_ICW4_EOI_MODE; typedef enum _PIC_I8259_ICW4_SYSTEM_MODE PIC_I8259_ICW4_SYSTEM_MODE, *PPIC_I8259_ICW4_SYSTEM_MODE; typedef enum _TIMER_TYPE TIMER_TYPE, *PTIMER_TYPE; typedef enum _TRAMPOLINE_TYPE TRAMPOLINE_TYPE, *PTRAMPOLINE_TYPE; /* Architecture-specific structures forward references */ typedef struct _CONTEXT CONTEXT, *PCONTEXT; typedef struct _CPU_IDENTIFICATION CPU_IDENTIFICATION, *PCPU_IDENTIFICATION; typedef struct _CPUID_REGISTERS CPUID_REGISTERS, *PCPUID_REGISTERS; typedef struct _CPUID_SIGNATURE CPUID_SIGNATURE, *PCPUID_SIGNATURE; typedef struct _FLOATING_SAVE_AREA FLOATING_SAVE_AREA, *PFLOATING_SAVE_AREA; typedef struct _HARDWARE_PTE HARDWARE_PTE, *PHARDWARE_PTE; typedef struct _HPET_REGISTERS HPET_REGISTERS, *PHPET_REGISTERS; typedef struct _IOAPIC_DATA IOAPIC_DATA, *PIOAPIC_DATA; typedef struct _KDESCRIPTOR KDESCRIPTOR, *PKDESCRIPTOR; typedef struct _KEXCEPTION_FRAME KEXCEPTION_FRAME, *PKEXCEPTION_FRAME; typedef struct _KGDTENTRY KGDTENTRY, *PKGDTENTRY; typedef struct _KIDTENTRY KIDTENTRY, *PKIDTENTRY; typedef struct _KPROCESSOR_BLOCK KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK; typedef struct _KPROCESSOR_CONTROL_BLOCK KPROCESSOR_CONTROL_BLOCK, *PKPROCESSOR_CONTROL_BLOCK; typedef struct _KPROCESSOR_STATE KPROCESSOR_STATE, *PKPROCESSOR_STATE; typedef struct _KSPECIAL_REGISTERS KSPECIAL_REGISTERS, *PKSPECIAL_REGISTERS; typedef struct _KSTART_FRAME KSTART_FRAME, *PKSTART_FRAME; typedef struct _KSWITCH_FRAME KSWITCH_FRAME, *PKSWITCH_FRAME; typedef struct _KTHREAD_INIT_FRAME KTHREAD_INIT_FRAME, *PKTHREAD_INIT_FRAME; typedef struct _KTRAP_FRAME KTRAP_FRAME, *PKTRAP_FRAME; typedef struct _KTSS KTSS, *PKTSS; typedef struct _MMPAGEMAP_INFO MMPAGEMAP_INFO, *PMMPAGEMAP_INFO; typedef struct _MMPFN MMPFN, *PMMPFN; typedef struct _MMPTE_HARDWARE MMPTE_HARDWARE, *PMMPTE_HARDWARE; typedef struct _MMPTE_HARDWARE_LARGEPAGE MMPTE_HARDWARE_LARGEPAGE, *PMMPTE_HARDWARE_LARGEPAGE; typedef struct _MMPTE_LIST MMPTE_LIST, *PMMPTE_LIST; typedef struct _MMPTE_PROTOTYPE MMPTE_PROTOTYPE, *PMMPTE_PROTOTYPE; typedef struct _MMPTE_SOFTWARE MMPTE_SOFTWARE, *PMMPTE_SOFTWARE; typedef struct _MMPTE_SUBSECTION MMPTE_SUBSECTION, *PMMPTE_SUBSECTION; typedef struct _MMPTE_TRANSITION MMPTE_TRANSITION, *PMMPTE_TRANSITION; typedef struct _POOL_DESCRIPTOR POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR; typedef struct _THREAD_ENVIRONMENT_BLOCK THREAD_ENVIRONMENT_BLOCK, *PTHREAD_ENVIRONMENT_BLOCK; typedef struct _TIMER_CAPABILITIES TIMER_CAPABILITIES, *PTIMER_CAPABILITIES; /* Unions forward references */ typedef union _APIC_BASE_REGISTER APIC_BASE_REGISTER, *PAPIC_BASE_REGISTER; typedef union _APIC_COMMAND_REGISTER APIC_COMMAND_REGISTER, *PAPIC_COMMAND_REGISTER; typedef union _APIC_LVT_REGISTER APIC_LVT_REGISTER, *PAPIC_LVT_REGISTER; typedef union _APIC_SPURIOUS_REGISTER APIC_SPURIOUS_REGISTER, *PAPIC_SPURIOUS_REGISTER; typedef union _IOAPIC_REDIRECTION_REGISTER IOAPIC_REDIRECTION_REGISTER, *PIOAPIC_REDIRECTION_REGISTER; typedef union _MMPTE MMP5E, *PMMP5E; typedef union _MMPTE MMPDE, *PMMPDE; typedef union _MMPTE MMPPE, *PMMPPE; typedef union _MMPTE MMPTE, *PMMPTE; typedef union _MMPTE MMPXE, *PMMPXE; typedef union _PIC_I8259_ICW1 PIC_I8259_ICW1, *PPIC_I8259_ICW1; typedef union _PIC_I8259_ICW2 PIC_I8259_ICW2, *PPIC_I8259_ICW2; typedef union _PIC_I8259_ICW3 PIC_I8259_ICW3, *PPIC_I8259_ICW3; typedef union _PIC_I8259_ICW4 PIC_I8259_ICW4, *PPIC_I8259_ICW4; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_AMD64_XTSTRUCT_H */ ================================================ FILE: sdk/xtdk/blfuncs.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/blfuncs.h * DESCRIPTION: XT Boot Manager routines * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_BLFUNCS_H #define __XTDK_BLFUNCS_H #include #include /* C/C++ specific code */ #ifndef D__XTOS_ASSEMBLER__ /* XT BootLoader routines forward references */ XTCLINK XTCDECL EFI_STATUS BlGetXtLdrProtocol(IN PEFI_SYSTEM_TABLE SystemTable, IN EFI_HANDLE ImageHandle, OUT PXTBL_LOADER_PROTOCOL *ProtocolHandler); #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_BLFUNCS_H */ ================================================ FILE: sdk/xtdk/bltarget.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/bltarget.h * DESCRIPTION: XT Boot Loader target architecture specific definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_BLTARGET_H #define __XTDK_BLTARGET_H #include /* Boot Loader module information macros */ #define MODULE_AUTHOR(_author) XTBL_MODULE_DATA(author, author, _author) #define MODULE_DEPENDENCY(_softdeps) XTBL_MODULE_DATA(softdeps, softdeps, _softdeps) #define MODULE_DESCRIPTION(_description) XTBL_MODULE_DATA(description, description, _description) #define MODULE_LICENSE(_license) XTBL_MODULE_DATA(license, license, _license) #define MODULE_VERSION(_version) XTBL_MODULE_DATA(version, version, _version) /* Boot Loader module information segment macro */ #define XTBL_MODULE_DATA(Tag, Name, Data) STATIC CONST WCHAR UNIQUE(Name)[] \ USED SEGMENT(".modinfo") ALIGN(1) \ = STRINGIFY(Tag) "=" Data /* XTLDR directories */ #define XTBL_LOADER_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR\\" #define XTBL_MODULES_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR\\MODULES\\" #define XTBL_THEMES_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR\\THEMES\\" /* Architecture specific definitions */ #if defined(__i386__) || defined(__i686__) #define XTBL_ARCH_LOADER_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR32\\" #define XTBL_ARCH_MODULES_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR32\\MODULES\\" #define XTBL_ARCH_THEMES_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR32\\THEMES\\" #elif defined(__amd64__) || defined(__x86_64__) #define XTBL_ARCH_LOADER_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR64\\" #define XTBL_ARCH_MODULES_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR64\\MODULES\\" #define XTBL_ARCH_THEMES_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR64\\THEMES\\" #else #error Unknown architecture #endif #endif /* __XTDK_BLTARGET_H */ ================================================ FILE: sdk/xtdk/bltypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/bltypes.h * DESCRIPTION: XT Boot Loader structures definitions * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #ifndef __XTDK_BLTYPES_H #define __XTDK_BLTYPES_H #include #include #include #include #include ARCH_HEADER(xtstruct.h) /* EFI XT boot devices */ #define XTBL_BOOT_DEVICE_UNKNOWN 0x00 #define XTBL_BOOT_DEVICE_ESP 0x01 #define XTBL_BOOT_DEVICE_CDROM 0x02 #define XTBL_BOOT_DEVICE_FLOPPY 0x04 #define XTBL_BOOT_DEVICE_HARDDISK 0x08 #define XTBL_BOOT_DEVICE_RAMDISK 0x10 /* XTLDR Debug Port type definitions */ #define XTBL_DEBUGPORT_SCREEN 1 #define XTBL_DEBUGPORT_SERIAL 2 /* XTLDR Shell definitions */ #define XTBL_SH_MAX_LINE_LENGTH 256 #define XTBL_SH_HISTORY_ENTRIES 20 /* TUI dialog box attributes */ #define XTBL_TUI_DIALOG_GENERIC_BOX 1 #define XTBL_TUI_DIALOG_ERROR_BOX 2 #define XTBL_TUI_DIALOG_ACTIVE_BUTTON 4 #define XTBL_TUI_DIALOG_INACTIVE_BUTTON 8 #define XTBL_TUI_DIALOG_ACTIVE_INPUT 16 #define XTBL_TUI_DIALOG_INACTIVE_INPUT 32 #define XTBL_TUI_DIALOG_PROGRESS_BAR 64 /* TUI dialog box maximum width */ #define XTBL_TUI_MAX_DIALOG_WIDTH 100 /* C/C++ specific code */ #ifndef D__XTOS_ASSEMBLER__ /* XTLDR Routine pointers */ typedef LOADER_MEMORY_TYPE (XTCDECL *PBL_GET_MEMTYPE_ROUTINE)(IN EFI_MEMORY_TYPE EfiMemoryType); /* Boot Loader protocol routine pointers */ typedef EFI_STATUS (XTCDECL *PBL_ALLOCATE_PAGES)(IN EFI_ALLOCATE_TYPE AllocationType, IN ULONGLONG Size, OUT PEFI_PHYSICAL_ADDRESS Memory); typedef EFI_STATUS (XTCDECL *PBL_ALLOCATE_POOL)(IN UINT_PTR Size, OUT PVOID *Memory); typedef EFI_STATUS (XTCDECL *PBL_BOOTMENU_INITIALIZE_OS_LIST)(IN ULONG MaxNameLength, OUT PXTBL_BOOTMENU_ITEM *MenuEntries, OUT PULONG EntriesCount, OUT PULONG DefaultId); typedef BOOLEAN (XTCDECL *PBL_BOOTUTILS_GET_BOOLEAN_PARAMETER)(IN PCWSTR Parameters, IN PCWSTR Needle); typedef VOID (XTAPI *PBL_BOOTUTILS_GET_TRAMPOLINE_INFORMATION)(IN TRAMPOLINE_TYPE TrampolineType, OUT PVOID *TrampolineCode, OUT PULONG_PTR TrampolineSize); typedef EFI_STATUS (XTCDECL *PBL_BUILD_PAGE_MAP)(IN PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR SelfMapAddress); typedef EFI_STATUS (XTCDECL *PBL_COMMIT_PAGE_MAP)(IN PXTBL_PAGE_MAPPING PageMap); typedef EFI_STATUS (XTCDECL *PBL_CLOSE_VOLUME)(IN PEFI_HANDLE VolumeHandle); typedef VOID (XTCDECL *PBL_CLEAR_CONSOLE_LINE)(IN ULONGLONG LineNo); typedef BOOLEAN (XTCDECL *PBL_CPU_CPUID)(IN OUT PCPUID_REGISTERS Registers); typedef ULONG_PTR (XTCDECL *PBL_CPU_READ_CONTROL_REGISTER)(IN USHORT ControlRegister); typedef ULONGLONG (XTCDECL *PBL_CPU_READ_MODEL_SPECIFIC_REGISTER)(IN ULONG Register); typedef VOID (XTCDECL *PBL_CPU_WRITE_CONTROL_REGISTER)(IN USHORT ControlRegister, IN UINT_PTR Value); typedef EFI_STATUS (XTCDECL *PBL_CLOSE_XT_PROTOCOL)(IN PEFI_HANDLE Handle, IN PEFI_GUID ProtocolGuid); typedef BOOLEAN (XTCDECL *PBL_CONFIG_GET_BOOLEAN_VALUE)(IN PCWSTR ConfigName); typedef EFI_STATUS (XTCDECL *PBL_CONFIG_GET_BOOT_OPTION_VALUE)(IN PLIST_ENTRY Options, IN PCWSTR OptionName, OUT PWCHAR *OptionValue); typedef VOID (XTCDECL *PBL_CONFIG_GET_EDITABLE_OPTIONS)(OUT PCWSTR **OptionsArray, OUT PULONG OptionsCount); typedef EFI_STATUS (XTCDECL *PBL_CONFIG_GET_VALUE)(IN PCWSTR ConfigName, OUT PWCHAR *ConfigValue); typedef EFI_STATUS (XTCDECL *PBL_CONFIG_SET_BOOT_OPTION_VALUE)(IN PLIST_ENTRY Options, IN PCWSTR OptionName, IN PCWSTR OptionValue); typedef VOID (XTCDECL *PBL_CONSOLE_CLEAR_SCREEN)(); typedef VOID (XTCDECL *PBL_CONSOLE_DISABLE_CURSOR)(); typedef VOID (XTCDECL *PBL_CONSOLE_ENABLE_CURSOR)(); typedef VOID (XTCDECL *PBL_CONSOLE_PRINT)(IN PCWSTR Format, IN ...); typedef VOID (XTCDECL *PBL_CONSOLE_QUERY_MODE)(OUT PUINT_PTR ResX, OUT PUINT_PTR ResY); typedef EFI_STATUS (XTCDECL *PBL_CONSOLE_READ_KEY_STROKE)(OUT PEFI_INPUT_KEY Key); typedef VOID (XTCDECL *PBL_CONSOLE_RESET_INPUT_BUFFER)(); typedef VOID (XTCDECL *PBL_CONSOLE_SET_ATTRIBUTES)(IN ULONGLONG Attributes); typedef VOID (XTCDECL *PBL_CONSOLE_SET_CURSOR_POSITION)(IN ULONGLONG PosX, IN ULONGLONG PosY); typedef VOID (XTCDECL *PBL_CONSOLE_WRITE)(IN PCWSTR String); typedef SIZE_T (XTAPI *PBL_COMPARE_MEMORY)(IN PCVOID LeftBuffer, IN PCVOID RightBuffer, IN SIZE_T Length); typedef SIZE_T (XTAPI *PBL_WIDESTRING_COMPARE)(IN PCWSTR String1, IN PCWSTR String2, IN SIZE_T Length); typedef VOID (XTAPI *PBL_COPY_MEMORY)(OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length); typedef VOID (XTCDECL *PBL_DEBUG_PRINT)(IN PCWSTR Format, IN ...); typedef EFI_STATUS (XTCDECL *PBL_ENTER_FIRMWARE_SETUP)(); typedef EFI_STATUS (XTCDECL *PBL_EXIT_BOOT_SERVICES)(); typedef EFI_STATUS (XTCDECL *PBL_FIND_BOOT_PROTOCOL)(IN PCWSTR SystemType, OUT PEFI_GUID BootProtocolGuid); typedef EFI_STATUS (XTCDECL *PBL_FREE_PAGES)(IN ULONGLONG Size, IN EFI_PHYSICAL_ADDRESS Memory); typedef EFI_STATUS (XTCDECL *PBL_FREE_POOL)(IN PVOID Memory); typedef EFI_STATUS (XTCDECL *PBL_GET_CONFIGURATION_TABLE)(IN PEFI_GUID TableGuid, OUT PVOID *Table); typedef EFI_STATUS (XTCDECL *PBL_GET_EFI_VARIABLE)(IN PEFI_GUID Vendor, IN PCWSTR VariableName, OUT PVOID *VariableValue); typedef VOID (XTCDECL *PBL_GET_MAPPINGS_COUNT)(IN PXTBL_PAGE_MAPPING PageMap, OUT PULONG NumberOfMappings); typedef EFI_STATUS (XTCDECL *PBL_GET_MEMORY_MAP)(OUT PEFI_MEMORY_MAP MemoryMap); typedef PLIST_ENTRY (XTCDECL *PBL_GET_MODULES_LIST)(); typedef ULONGLONG (XTCDECL *PBL_GET_RANDOM_VALUE)(IN OUT PULONGLONG RNGBuffer); typedef INT_PTR (XTCDECL *PBL_GET_SECURE_BOOT_STATUS)(); typedef PVOID (XTCDECL *PBL_GET_VIRTUAL_ADDRESS)(IN PXTBL_PAGE_MAPPING PageMap, IN PVOID PhysicalAddress); typedef EFI_STATUS (XTCDECL *PBL_INITIALIZE_ENTROPY)(PULONGLONG RNGBuffer); typedef VOID (XTCDECL *PBL_INITIALIZE_PAGE_MAP)(OUT PXTBL_PAGE_MAPPING PageMap, IN SHORT PageMapLevel, IN PAGE_SIZE PageSize); typedef EFI_STATUS (XTCDECL *PBL_INSTALL_XT_PROTOCOL)(IN PVOID Interface, IN PEFI_GUID Guid); typedef EFI_STATUS (XTCDECL *PBL_INVOKE_BOOT_PROTOCOL)(IN PWCHAR ShortName, IN PLIST_ENTRY OptionsList); typedef EFI_STATUS (XTCDECL *PBL_LOCATE_PROTOCOL_HANDLES)(OUT PEFI_HANDLE *Handles, OUT PUINT_PTR Count, IN PEFI_GUID ProtocolGuid); typedef EFI_STATUS (XTCDECL *PBL_LOAD_EFI_IMAGE)(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, IN PVOID ImageData, IN SIZE_T ImageSize, OUT PEFI_HANDLE ImageHandle); typedef VOID (XTCDECL *PBL_LLIST_INITIALIZE_HEAD)(IN PLIST_ENTRY ListHead); typedef VOID (XTCDECL *PBL_LLIST_INSERT_HEAD)(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); typedef VOID (XTCDECL *PBL_LLIST_INSERT_TAIL)(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); typedef VOID (XTCDECL *PBL_LLIST_REMOVE_ENTRY)(IN PLIST_ENTRY Entry); typedef EFI_STATUS (XTCDECL *PBL_MAP_EFI_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN OUT PVOID *BaseAddress, IN BOOLEAN IdentityMapping, IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine); typedef EFI_STATUS (XTCDECL *PBL_MAP_PAGE)(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages); typedef EFI_STATUS (XTCDECL *PBL_MAP_VIRTUAL_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); typedef VOID (XTAPI *PBL_MOVE_MEMORY)(IN OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length); typedef EFI_STATUS (XTCDECL *PBL_OPEN_VOLUME)(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_HANDLE DiskHandle, OUT PEFI_FILE_HANDLE *FsHandle); typedef EFI_STATUS (XTCDECL *PBL_OPEN_PROTOCOL)(OUT PEFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); typedef EFI_STATUS (XTCDECL *PBL_OPEN_PROTOCOL_HANDLE)(IN EFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); typedef PVOID (XTCDECL *PBL_PHYSICAL_ADDRESS_TO_VIRTUAL)(IN PVOID PhysicalAddress, IN PVOID PhysicalBase, IN PVOID VirtualBase); typedef UCHAR (XTCDECL *PBL_IOPORT_READ_8)(IN USHORT Port); typedef USHORT (XTCDECL *PBL_IOPORT_READ_16)(IN USHORT Port); typedef ULONG (XTCDECL *PBL_IOPORT_READ_32)(IN USHORT Port); typedef VOID (XTCDECL *PBL_IOPORT_WRITE_8)(IN USHORT Port, IN UCHAR Value); typedef VOID (XTCDECL *PBL_IOPORT_WRITE_16)(IN USHORT Port, IN USHORT Value); typedef VOID (XTCDECL *PBL_IOPORT_WRITE_32)(IN USHORT Port, IN ULONG Value); typedef EFI_STATUS (XTCDECL *PBL_PHYSICAL_LIST_TO_VIRTUAL)(IN PXTBL_PAGE_MAPPING PageMap, IN OUT PLIST_ENTRY ListHead, IN PVOID PhysicalBase, IN PVOID VirtualBase); typedef EFI_STATUS (XTCDECL *PBL_POWER_SYSTEM)(); typedef EFI_STATUS (XTCDECL *PBL_READ_FILE)(IN PEFI_FILE_HANDLE DirHandle, IN PCWSTR FileName, OUT PVOID *FileData, OUT PSIZE_T FileSize); typedef EFI_STATUS (XTCDECL *PBL_REGISTER_BOOT_PROTOCOL)(IN PCWSTR SystemType, IN PEFI_GUID BootProtocolGuid); typedef VOID (XTCDECL *PBL_REGISTER_XT_BOOT_MENU)(PVOID BootMenuRoutine); typedef EFI_STATUS (XTCDECL *PBL_SET_EFI_VARIABLE)(IN PEFI_GUID Vendor, IN PCWSTR VariableName, IN PVOID VariableValue, IN UINT_PTR Size); typedef SIZE_T (XTAPI *PBL_STRING_COMPARE)(IN PCSTR String1, IN PCSTR String2, IN SIZE_T Length); typedef SIZE_T (XTAPI *PBL_STRING_LENGTH)(IN PCSTR String, IN SIZE_T MaxLength); typedef SIZE_T (XTAPI *PBL_STRING_TO_WIDESTRING)(OUT PWCHAR Destination, IN PCSTR *Source, IN SIZE_T Length); typedef PCHAR (XTAPI *PBL_STRING_TRIM)(IN PCHAR String); typedef VOID (XTAPI *PBL_SET_MEMORY)(OUT PVOID Destination, IN UCHAR Byte, IN SIZE_T Length); typedef VOID (XTCDECL *PBL_SLEEP_EXECUTION)(IN ULONG_PTR Milliseconds); typedef EFI_STATUS (XTCDECL *PBL_START_EFI_IMAGE)(IN EFI_HANDLE ImageHandle); typedef VOID (XTCDECL *PBL_TUI_DISPLAY_ERROR_DIALOG)(IN PCWSTR Caption, IN PCWSTR Message); typedef VOID (XTCDECL *PBL_TUI_DISPLAY_INFO_DIALOG)(IN PCWSTR Caption, IN PCWSTR Message); typedef VOID (XTCDECL *PBL_TUI_DISPLAY_INPUT_DIALOG)(IN PCWSTR Caption, IN PCWSTR Message, IN OUT PWCHAR *InputFieldText); typedef XTBL_DIALOG_HANDLE (XTCDECL *PBL_TUI_DISPLAY_PROGRESS_DIALOG)(IN PCWSTR Caption, IN PCWSTR Message, IN UCHAR Percentage); typedef VOID (XTCDECL *PBL_TUI_UPDATE_PROGRESS_BAR)(IN PXTBL_DIALOG_HANDLE Handle, IN PCWSTR Message, IN UCHAR Percentage); typedef SIZE_T (XTAPI *PBL_WIDESTRING_COMPARE_INSENSITIVE)(IN PCWSTR String1, IN PCWSTR String2, IN SIZE_T Length); typedef PWCHAR (XTAPI *PBL_WIDESTRING_CONCATENATE)(OUT PWCHAR Destination, IN PWCHAR Source, IN SIZE_T Count); typedef XTSTATUS (XTAPI *PBL_WIDESTRING_FORMAT)(IN PRTL_PRINT_CONTEXT Context, IN PCWSTR Format, IN VA_LIST ArgumentList); typedef SIZE_T (XTAPI *PBL_WIDESTRING_LENGTH)(IN PCWSTR String, IN SIZE_T MaxLength); typedef PWCHAR (XTAPI *PBL_WIDESTRING_TOKENIZE)(IN PWCHAR String, IN PCWSTR Delimiter, IN OUT PWCHAR *SavePtr); typedef EFI_STATUS (XTCDECL *PBL_WAIT_FOR_EFI_EVENT)(IN UINT_PTR NumberOfEvents, IN PEFI_EVENT Event, OUT PUINT_PTR Index); typedef VOID (XTCDECL *PBL_SHELL_COMMAND)(IN ULONG Argc, IN PWCHAR *Argv); typedef EFI_STATUS (XTCDECL *PBL_REGISTER_SHELL_COMMAND)(IN PCWSTR Command, IN PCWSTR Description, IN PBL_SHELL_COMMAND Handler); typedef VOID (XTCDECL *PBL_XT_BOOT_MENU)(); typedef VOID (XTAPI *PBL_ZERO_MEMORY)(OUT PVOID Destination, IN SIZE_T Length); /* Module protocols routine pointers */ typedef EFI_STATUS (XTCDECL *PBL_ACPI_GET_ACPI_DESCRIPTION_POINTER)(OUT PVOID *AcpiTable); typedef EFI_STATUS (XTCDECL *PBL_ACPI_GET_ACPI_TABLE)(IN CONST UINT Signature, IN PVOID PreviousTable, OUT PVOID *AcpiTable); typedef EFI_STATUS (XTCDECL *PBL_ACPI_GET_APIC_BASE)(OUT PVOID *ApicBase); typedef EFI_STATUS (XTCDECL *PBL_ACPI_GET_RSDP_TABLE)(OUT PVOID *AcpiTable); typedef EFI_STATUS (XTCDECL *PBL_ACPI_GET_SMBIOS_TABLE)(OUT PVOID *SmBiosTable); typedef EFI_STATUS (XTCDECL *PBL_ACPI_GET_SMBIOS3_TABLE)(OUT PVOID *SmBiosTable); typedef EFI_STATUS (XTCDECL *PBL_ACPI_GET_XSDP_TABLE)(OUT PVOID *AcpiTable); typedef EFI_STATUS (XTCDECL *PBL_BOOTPROTO_BOOT_SYSTEM)(IN PXTBL_BOOT_PARAMETERS Parameters); typedef EFI_STATUS (XTCDECL *PBL_EXECIMAGE_GET_ENTRY_POINT)(IN PVOID ImagePointer, OUT PVOID *EntryPoint); typedef EFI_STATUS (XTCDECL *PBL_EXECIMAGE_GET_FILE_SIZE)(IN PVOID ImagePointer, OUT PULONGLONG FileSize); typedef EFI_STATUS (XTCDECL *PBL_EXECIMAGE_GET_IMAGE_SIZE)(IN PVOID ImagePointer, OUT PUINT ImageSize); typedef EFI_STATUS (XTCDECL *PBL_EXECIMAGE_GET_MACHINE_TYPE)(IN PVOID ImagePointer, OUT PUSHORT MachineType); typedef EFI_STATUS (XTCDECL *PBL_EXECIMAGE_GET_SECTION)(IN PVOID ImagePointer, IN PCHAR SectionName, OUT PULONG *RawData); typedef EFI_STATUS (XTCDECL *PBL_EXECIMAGE_GET_SUBSYSTEM)(IN PVOID ImagePointer, OUT PUSHORT SubSystem); typedef EFI_STATUS (XTCDECL *PBL_EXECIMAGE_GET_VERSION)(IN PVOID ImagePointer, OUT PUSHORT Version); typedef EFI_STATUS (XTCDECL *PBL_EXECIMAGE_LOAD_IMAGE)(IN PEFI_FILE_HANDLE FileHandle, IN LOADER_MEMORY_TYPE MemoryType, IN PVOID VirtualAddress, OUT PVOID *ImagePointer); typedef EFI_STATUS (XTCDECL *PBL_EXECIMAGE_RELOCATE_IMAGE)(IN PVOID ImagePointer, IN EFI_VIRTUAL_ADDRESS Address); typedef EFI_STATUS (XTCDECL *PBL_EXECIMAGE_UNLOAD_IMAGE)(IN PVOID ImagePointer); typedef EFI_STATUS (XTCDECL *PBL_EXECIMAGE_VERIFY_IMAGE)(IN PVOID ImagePointer); typedef EFI_STATUS (XTCDECL *PBL_FRAMEBUFFER_GET_DISPLAY_DRIVER)(OUT PEFI_GRAPHICS_PROTOCOL Protocol); typedef EFI_STATUS (XTCDECL *PBL_FRAMEBUFFER_GET_DISPLAY_INFORMATION)(OUT PEFI_PHYSICAL_ADDRESS FrameBufferBase, OUT PULONG_PTR FrameBufferSize, OUT PXTBL_FRAMEBUFFER_MODE_INFORMATION ModeInfo); typedef EFI_STATUS (XTCDECL *PBL_FRAMEBUFFER_GET_PREFERRED_SCREEN_RESOLUTION)(OUT PUINT PreferredWidth, OUT PUINT PreferredHeight); typedef EFI_STATUS (XTCDECL *PBL_FRAMEBUFFER_INITIALIZE)(); typedef EFI_STATUS (XTCDECL *PBL_FRAMEBUFFER_SET_SCREEN_RESOLUTION)(IN UINT Width, IN UINT Height); /* Boot parameters structure */ typedef struct _XTBL_BOOT_PARAMETERS { PEFI_DEVICE_PATH_PROTOCOL DevicePath; PWCHAR ArcName; PWCHAR EfiPath; PWCHAR SystemPath; PWCHAR SystemType; PWCHAR KernelFile; PWCHAR InitrdFile; PWCHAR HalFile; PWCHAR Parameters; } XTBL_BOOT_PARAMETERS, *PXTBL_BOOT_PARAMETERS; /* Boot menu list structure */ typedef struct _XTBL_BOOTMENU_ITEM { PWCHAR EntryName; PWCHAR FullName; PWCHAR ShortName; PLIST_ENTRY Options; } XTBL_BOOTMENU_ITEM, *PXTBL_BOOTMENU_ITEM; /* XTLDR Configuration data */ typedef struct _XTBL_CONFIG_ENTRY { LIST_ENTRY Flink; PWCHAR Name; PWCHAR Value; } XTBL_CONFIG_ENTRY, *PXTBL_CONFIG_ENTRY; /* XTLDR Configuration section */ typedef struct _XTBL_CONFIG_SECTION { LIST_ENTRY Flink; LIST_ENTRY Options; PWCHAR SectionName; } XTBL_CONFIG_SECTION, *PXTBL_CONFIG_SECTION; /* XTLDR Dialog handle data */ typedef struct _XTBL_DIALOG_HANDLE { UCHAR Attributes; UCHAR DialogColor; UCHAR TextColor; UINT_PTR ResX; UINT_PTR ResY; UINT_PTR PosX; UINT_PTR PosY; UINT_PTR Width; UINT_PTR Height; } XTBL_DIALOG_HANDLE, *PXTBL_DIALOG_HANDLE; /* Registered boot protocol structure */ typedef struct _XTBL_KNOWN_BOOT_PROTOCOL { LIST_ENTRY Flink; PWCHAR SystemType; EFI_GUID Guid; } XTBL_KNOWN_BOOT_PROTOCOL, *PXTBL_KNOWN_BOOT_PROTOCOL; /* XTLDR Shell command entry */ typedef struct _XTBL_SHELL_COMMAND { LIST_ENTRY Flink; PWCHAR Command; PWCHAR Description; PBL_SHELL_COMMAND Handler; } XTBL_SHELL_COMMAND, *PXTBL_SHELL_COMMAND; /* Boot Loader memory mapping information */ typedef struct _XTBL_MEMORY_MAPPING { LIST_ENTRY ListEntry; ULONGLONG VirtualAddress; ULONGLONG PhysicalAddress; ULONGLONG NumberOfPages; LOADER_MEMORY_TYPE MemoryType; } XTBL_MEMORY_MAPPING, *PXTBL_MEMORY_MAPPING; /* XTLDR Module dependencies data */ typedef struct _XTBL_MODULE_AUTHORS { LIST_ENTRY Flink; PWCHAR AuthorName; } XTBL_MODULE_AUTHORS, *PXTBL_MODULE_AUTHORS; /* XTLDR Module dependencies data */ typedef struct _XTBL_MODULE_DEPS { LIST_ENTRY Flink; PWCHAR ModuleName; } XTBL_MODULE_DEPS, *PXTBL_MODULE_DEPS; /* XTLDR Module information data */ typedef struct _XTBL_MODULE_INFO { LIST_ENTRY Flink; PWCHAR ModuleName; PWCHAR ModuleDescription; PWCHAR License; PWCHAR Version; LIST_ENTRY Authors; LIST_ENTRY Dependencies; PVOID ModuleBase; ULONGLONG ModuleSize; UINT Revision; PEFI_IMAGE_UNLOAD UnloadModule; } XTBL_MODULE_INFO, *PXTBL_MODULE_INFO; /* Boot Loader page mapping information */ typedef struct _XTBL_PAGE_MAPPING { LIST_ENTRY MemoryMap; ULONG MapSize; PVOID PtePointer; SHORT PageMapLevel; PAGE_SIZE PageSize; } XTBL_PAGE_MAPPING, *PXTBL_PAGE_MAPPING; /* XTLDR Status data */ typedef struct _XTBL_STATUS { PVOID LoaderBase; ULONGLONG LoaderSize; BOOLEAN BootServices; INT_PTR SecureBoot; } XTBL_STATUS, *PXTBL_STATUS; /* XT framebuffer video mode information structure definition */ typedef struct _XTBL_FRAMEBUFFER_MODE_INFORMATION { UINT Width; UINT Height; UINT Depth; UINT RefreshRate; UINT BitsPerPixel; UINT BytesPerPixel; UINT PixelsPerScanLine; UINT Pitch; EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; struct { USHORT BlueShift; USHORT BlueSize; USHORT GreenShift; USHORT GreenSize; USHORT RedShift; USHORT RedSize; USHORT ReservedShift; USHORT ReservedSize; } PixelInformation; } XTBL_FRAMEBUFFER_MODE_INFORMATION, *PXTBL_FRAMEBUFFER_MODE_INFORMATION; /* XT framebuffer information structure definition */ typedef struct _XTBL_FRAMEBUFFER_INFORMATION { BOOLEAN Initialized; EFI_GRAPHICS_PROTOCOL Protocol; EFI_PHYSICAL_ADDRESS FrameBufferBase; ULONG_PTR FrameBufferSize; UINT DefaultMode; EFI_HANDLE Handle; union { PEFI_GRAPHICS_OUTPUT_PROTOCOL Gop; PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL Uga; } Driver; XTBL_FRAMEBUFFER_MODE_INFORMATION ModeInfo; } XTBL_FRAMEBUFFER_INFORMATION, *PXTBL_FRAMEBUFFER_INFORMATION; /* XTLDR ACPI protocol structure */ typedef struct _XTBL_ACPI_PROTOCOL { PBL_ACPI_GET_ACPI_DESCRIPTION_POINTER GetAcpiDescriptionPointer; PBL_ACPI_GET_ACPI_TABLE GetAcpiTable; PBL_ACPI_GET_APIC_BASE GetApicBase; PBL_ACPI_GET_RSDP_TABLE GetRsdpTable; PBL_ACPI_GET_SMBIOS_TABLE GetSMBiosTable; PBL_ACPI_GET_SMBIOS3_TABLE GetSMBios3Table; PBL_ACPI_GET_XSDP_TABLE GetXsdpTable; } XTBL_ACPI_PROTOCOL, *PXTBL_ACPI_PROTOCOL; /* XTLDR Boot protocol structure */ typedef struct _XTBL_BOOT_PROTOCOL { PBL_BOOTPROTO_BOOT_SYSTEM BootSystem; } XTBL_BOOT_PROTOCOL, *PXTBL_BOOT_PROTOCOL; /* XTLDR Executable image protocol structure */ typedef struct _XTBL_EXECUTABLE_IMAGE_PROTOCOL { PBL_EXECIMAGE_GET_ENTRY_POINT GetEntryPoint; PBL_EXECIMAGE_GET_FILE_SIZE GetFileSize; PBL_EXECIMAGE_GET_IMAGE_SIZE GetImageSize; PBL_EXECIMAGE_GET_MACHINE_TYPE GetMachineType; PBL_EXECIMAGE_GET_SECTION GetSection; PBL_EXECIMAGE_GET_SUBSYSTEM GetSubSystem; PBL_EXECIMAGE_GET_VERSION GetVersion; PBL_EXECIMAGE_LOAD_IMAGE LoadImage; PBL_EXECIMAGE_RELOCATE_IMAGE RelocateImage; PBL_EXECIMAGE_UNLOAD_IMAGE UnloadImage; PBL_EXECIMAGE_VERIFY_IMAGE VerifyImage; } XTBL_EXECUTABLE_IMAGE_PROTOCOL, *PXTBL_EXECUTABLE_IMAGE_PROTOCOL; /* XT framebuffer support protocol structure */ typedef struct _XTBL_FRAMEBUFFER_PROTOCOL { PBL_FRAMEBUFFER_GET_DISPLAY_DRIVER GetDisplayDriver; PBL_FRAMEBUFFER_GET_DISPLAY_INFORMATION GetDisplayInformation; PBL_FRAMEBUFFER_GET_PREFERRED_SCREEN_RESOLUTION GetPreferredScreenResolution; PBL_FRAMEBUFFER_INITIALIZE Initialize; PBL_FRAMEBUFFER_SET_SCREEN_RESOLUTION SetScreenResolution; } XTBL_FRAMEBUFFER_PROTOCOL, *PXTBL_FRAMEBUFFER_PROTOCOL; /* XTLDR Loader protocol structure */ typedef struct _XTBL_LOADER_PROTOCOL { struct { PBL_FIND_BOOT_PROTOCOL FindProtocol; PBL_BOOTMENU_INITIALIZE_OS_LIST InitializeMenuList; PBL_INVOKE_BOOT_PROTOCOL InvokeProtocol; PBL_REGISTER_XT_BOOT_MENU RegisterMenu; PBL_REGISTER_BOOT_PROTOCOL RegisterProtocol; } Boot; struct { PBL_BOOTUTILS_GET_BOOLEAN_PARAMETER GetBooleanParameter; PBL_BOOTUTILS_GET_TRAMPOLINE_INFORMATION GetTrampolineInformation; } BootUtils; struct { PBL_CONFIG_GET_BOOLEAN_VALUE GetBooleanValue; PBL_CONFIG_GET_BOOT_OPTION_VALUE GetBootOptionValue; PBL_CONFIG_GET_EDITABLE_OPTIONS GetEditableOptions; PBL_CONFIG_GET_VALUE GetValue; PBL_CONFIG_SET_BOOT_OPTION_VALUE SetBootOptionValue; } Config; struct { PBL_CLEAR_CONSOLE_LINE ClearLine; PBL_CONSOLE_CLEAR_SCREEN ClearScreen; PBL_CONSOLE_DISABLE_CURSOR DisableCursor; PBL_CONSOLE_ENABLE_CURSOR EnableCursor; PBL_CONSOLE_PRINT Print; PBL_CONSOLE_QUERY_MODE QueryMode; PBL_CONSOLE_READ_KEY_STROKE ReadKeyStroke; PBL_CONSOLE_RESET_INPUT_BUFFER ResetInputBuffer; PBL_CONSOLE_SET_ATTRIBUTES SetAttributes; PBL_CONSOLE_SET_CURSOR_POSITION SetCursorPosition; PBL_CONSOLE_WRITE Write; } Console; struct { PBL_CPU_CPUID CpuId; PBL_CPU_READ_CONTROL_REGISTER ReadControlRegister; PBL_CPU_READ_MODEL_SPECIFIC_REGISTER ReadModelSpecificRegister; PBL_CPU_WRITE_CONTROL_REGISTER WriteControlRegister; } Cpu; struct { PBL_DEBUG_PRINT Print; } Debug; struct { PBL_CLOSE_VOLUME CloseVolume; PBL_OPEN_VOLUME OpenVolume; PBL_READ_FILE ReadFile; } Disk; struct { PBL_IOPORT_READ_8 Read8; PBL_IOPORT_READ_16 Read16; PBL_IOPORT_READ_32 Read32; PBL_IOPORT_WRITE_8 Write8; PBL_IOPORT_WRITE_16 Write16; PBL_IOPORT_WRITE_32 Write32; } IoPort; struct { PBL_LLIST_INITIALIZE_HEAD InitializeHead; PBL_LLIST_INSERT_HEAD InsertHead; PBL_LLIST_INSERT_TAIL InsertTail; PBL_LLIST_REMOVE_ENTRY RemoveEntry; } LinkedList; struct { PBL_ALLOCATE_PAGES AllocatePages; PBL_ALLOCATE_POOL AllocatePool; PBL_BUILD_PAGE_MAP BuildPageMap; PBL_COMMIT_PAGE_MAP CommitPageMap; PBL_COMPARE_MEMORY CompareMemory; PBL_COPY_MEMORY CopyMemory; PBL_FREE_PAGES FreePages; PBL_FREE_POOL FreePool; PBL_GET_MAPPINGS_COUNT GetMappingsCount; PBL_GET_MEMORY_MAP GetMemoryMap; PBL_GET_VIRTUAL_ADDRESS GetVirtualAddress; PBL_INITIALIZE_PAGE_MAP InitializePageMap; PBL_MAP_EFI_MEMORY MapEfiMemory; PBL_MAP_PAGE MapPage; PBL_MAP_VIRTUAL_MEMORY MapVirtualMemory; PBL_MOVE_MEMORY MoveMemory; PBL_PHYSICAL_ADDRESS_TO_VIRTUAL PhysicalAddressToVirtual; PBL_PHYSICAL_LIST_TO_VIRTUAL PhysicalListToVirtual; PBL_SET_MEMORY SetMemory; PBL_ZERO_MEMORY ZeroMemory; } Memory; struct { PBL_CLOSE_XT_PROTOCOL Close; PBL_GET_MODULES_LIST GetModulesList; PBL_INSTALL_XT_PROTOCOL Install; PBL_LOCATE_PROTOCOL_HANDLES LocateHandles; PBL_OPEN_PROTOCOL Open; PBL_OPEN_PROTOCOL_HANDLE OpenHandle; } Protocol; struct { PBL_REGISTER_SHELL_COMMAND RegisterCommand; } Shell; struct { PBL_STRING_COMPARE Compare; PBL_STRING_LENGTH Length; PBL_STRING_TO_WIDESTRING ToWideString; PBL_STRING_TRIM Trim; } String; struct { PBL_TUI_DISPLAY_ERROR_DIALOG DisplayErrorDialog; PBL_TUI_DISPLAY_INFO_DIALOG DisplayInfoDialog; PBL_TUI_DISPLAY_INPUT_DIALOG DisplayInputDialog; PBL_TUI_DISPLAY_PROGRESS_DIALOG DisplayProgressDialog; PBL_TUI_UPDATE_PROGRESS_BAR UpdateProgressBar; } Tui; struct { PBL_ENTER_FIRMWARE_SETUP EnterFirmwareSetup; PBL_EXIT_BOOT_SERVICES ExitBootServices; PBL_GET_CONFIGURATION_TABLE GetConfigurationTable; PBL_GET_EFI_VARIABLE GetEfiVariable; PBL_GET_RANDOM_VALUE GetRandomValue; PBL_GET_SECURE_BOOT_STATUS GetSecureBootStatus; PBL_INITIALIZE_ENTROPY InitializeEntropy; PBL_LOAD_EFI_IMAGE LoadEfiImage; PBL_POWER_SYSTEM RebootSystem; PBL_SET_EFI_VARIABLE SetEfiVariable; PBL_POWER_SYSTEM ShutdownSystem; PBL_SLEEP_EXECUTION SleepExecution; PBL_START_EFI_IMAGE StartEfiImage; PBL_WAIT_FOR_EFI_EVENT WaitForEfiEvent; } Utils; struct { PBL_WIDESTRING_COMPARE Compare; PBL_WIDESTRING_COMPARE_INSENSITIVE CompareInsensitive; PBL_WIDESTRING_CONCATENATE Concatenate; PBL_WIDESTRING_FORMAT Format; PBL_WIDESTRING_LENGTH Length; PBL_WIDESTRING_TOKENIZE Tokenize; } WideString; } XTBL_LOADER_PROTOCOL, *PXTBL_LOADER_PROTOCOL; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_BLTYPES_H */ ================================================ FILE: sdk/xtdk/exfuncs.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/exfuncs.h * DESCRIPTION: Kernel executive routines * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_EXFUNCS_H #define __XTDK_EXFUNCS_H #include #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Kernel Executive routines forward references */ XTCLINK XTFASTCALL BOOLEAN ExAcquireRundownProtection(IN PEX_RUNDOWN_REFERENCE Descriptor); XTCLINK XTFASTCALL VOID ExCompleteRundownProtection(IN PEX_RUNDOWN_REFERENCE Descriptor); XTCLINK XTFASTCALL VOID ExInitializeRundownProtection(IN PEX_RUNDOWN_REFERENCE Descriptor); XTCLINK XTFASTCALL VOID ExReInitializeRundownProtection(IN PEX_RUNDOWN_REFERENCE Descriptor); XTCLINK XTFASTCALL VOID ExReleaseRundownProtection(IN PEX_RUNDOWN_REFERENCE Descriptor); XTCLINK XTFASTCALL VOID ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REFERENCE Descriptor); #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_EXFUNCS_H */ ================================================ FILE: sdk/xtdk/extypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/extypes.h * DESCRIPTION: Kernel executive structures definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_EXTYPES_H #define __XTDK_EXTYPES_H #include #include #include /* Rundown protection flags */ #define EX_RUNDOWN_ACTIVE 0x1 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Executive rundown protection structure definition */ typedef struct _EX_RUNDOWN_REFERENCE { union { ULONG_PTR Count; PVOID Ptr; }; } EX_RUNDOWN_REFERENCE, *PEX_RUNDOWN_REFERENCE; /* Executive rundown wait block definition */ typedef struct _EX_RUNDOWN_WAIT_BLOCK { ULONG_PTR Count; KEVENT WakeEvent; } EX_RUNDOWN_WAIT_BLOCK, *PEX_RUNDOWN_WAIT_BLOCK; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_EXTYPES_H */ ================================================ FILE: sdk/xtdk/hlfuncs.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/hlfuncs.h * DESCRIPTION: XT hardware abstraction layer routines * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_HLFUNCS_H #define __XTDK_HLFUNCS_H #include #include #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Hardware layer routines forward references */ XTCLINK XTAPI LARGE_INTEGER HlQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceFrequency); XTCLINK XTAPI UCHAR HlReadRegister8(IN PVOID Register); XTCLINK XTAPI USHORT HlReadRegister16(IN PVOID Register); XTCLINK XTAPI ULONG HlReadRegister32(IN PVOID Register); XTCLINK XTAPI ULONG HlSetClockRate(IN ULONG Rate); XTCLINK XTAPI VOID HlWriteRegister8(IN PVOID Register, IN UCHAR Value); XTCLINK XTAPI VOID HlWriteRegister16(IN PVOID Register, IN USHORT Value); XTCLINK XTAPI VOID HlWriteRegister32(IN PVOID Register, IN ULONG Value); #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_HLFUNCS_H */ ================================================ FILE: sdk/xtdk/hltypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/hltypes.h * DESCRIPTION: XT hardware abstraction layer structures definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_HLTYPES_H #define __XTDK_HLTYPES_H #include #include #include #include ARCH_HEADER(hltypes.h) /* ACPI Root System Description Pointer (RSDP) signature */ #define ACPI_RSDP_SIGNATURE 0x2052545020445352 /* ACPI table signatures */ #define ACPI_BERT_SIGNATURE 0x54524542 /* Boot Error Record Table */ #define ACPI_BGRT_SIGNATURE 0x54524742 /* Boot Graphics Record Table */ #define ACPI_BOOT_SIGNATURE 0x544F4F42 /* ACPI BOOT Table */ #define ACPI_CPEP_SIGNATURE 0x50455043 /* Corrected Platform Error Polling Table */ #define ACPI_DBG2_SIGNATURE 0x32474244 /* Debug Port Table v2 */ #define ACPI_DBGP_SIGNATURE 0x50474244 /* Debug Port Table */ #define ACPI_DMAR_SIGNATURE 0x52414D44 /* DMA Remapping Table */ #define ACPI_DSDT_SIGNATURE 0x54445344 /* Differentiated System Description Table */ #define ACPI_ECDT_SIGNATURE 0x54444345 /* Embedded Controller Description Table */ #define ACPI_ERST_SIGNATURE 0x54535245 /* Error Record Serialization Table */ #define ACPI_FACS_SIGNATURE 0x53434146 /* Firmware ACPI Control Structure */ #define ACPI_FADT_SIGNATURE 0x50434146 /* Fixed ACPI Description Table */ #define ACPI_FBPT_SIGNATURE 0x54504246 /* Firmware Boot Performance Table */ #define ACPI_FPDT_SIGNATURE 0x54445046 /* Firmware Performance Data Table */ #define ACPI_GTDT_SIGNATURE 0x54445447 /* Generic Timer Description Table */ #define ACPI_HPET_SIGNATURE 0x54455048 /* High Precision Event Timer */ #define ACPI_IVRS_SIGNATURE 0x53525649 /* AMD IOMMU Resource Table */ #define ACPI_MADT_SIGNATURE 0x43495041 /* MADT/APIC Description Table */ #define ACPI_MCFG_SIGNATURE 0x4746434D /* Memory Mapped Configuration Space Access Table */ #define ACPI_MPST_SIGNATURE 0x5453504D /* Memory Power State Table*/ #define ACPI_MSCT_SIGNATURE 0x5443534D /* Maximum System Characteristics Table */ #define ACPI_NFIT_SIGNATURE 0x5449464E /* NVDIMM Firmware Interface Table */ #define ACPI_PMMT_SIGNATURE 0x544D4D50 /* Platform Memory Topology Table */ #define ACPI_PSDT_SIGNATURE 0x54445350 /* Persistent System Description Table */ #define ACPI_RAS2_SIGNATURE 0x32534152 /* ACPI RAS2 Feature Table */ #define ACPI_RASF_SIGNATURE 0x46534152 /* ACPI RAS Feature Table */ #define ACPI_RSDT_SIGNATURE 0x54445352 /* Root System Description Table */ #define ACPI_SBST_SIGNATURE 0x54534253 /* Smart Battery Subsystem Table */ #define ACPI_SDEV_SIGNATURE 0x56454453 /* Secure Device Table */ #define ACPI_SLIT_SIGNATURE 0x54494C53 /* System Locality Distance Information Table */ #define ACPI_SPCR_SIGNATURE 0x52435053 /* Serial Port Console Redirection Table */ #define ACPI_SRAT_SIGNATURE 0x54415253 /* Static Resource Affinity Table */ #define ACPI_SSDT_SIGNATURE 0x54445353 /* Secondary System Descriptor Table */ #define ACPI_TPM2_SIGNATURE 0x324D5054 /* ACPI TPM 2.0 Table */ #define ACPI_WAET_SIGNATURE 0x54454157 /* Windows ACPI Enlightenment Table */ #define ACPI_WDAT_SIGNATURE 0x54414457 /* Watch Dog Action Table */ #define ACPI_WDTT_SIGNATURE 0x54524457 /* Watchdog Timer Resource Table */ #define ACPI_WPBT_SIGNATURE 0x54425057 /* Windows Platform Binary Table */ #define ACPI_WSMT_SIGNATURE 0x544D5357 /* Windows SMM Security Mitigation Table */ #define ACPI_XSDT_SIGNATURE 0x54445358 /* eXtended System Descriptor Table */ /* ACPI FADT flags masks */ #define ACPI_FADT_32BIT_TIMER (1<<8) /* ACPI Timer bit masks */ #define ACPI_FADT_TIMER_32BIT 0xFFFFFFFF #define ACPI_FADT_TIMER_24BIT 0x00FFFFFF /* ACPI MADT subtable type definitions */ #define ACPI_MADT_TYPE_LOCAL_APIC 0 #define ACPI_MADT_TYPE_IOAPIC 1 #define ACPI_MADT_TYPE_INT_OVERRIDE 2 #define ACPI_MADT_TYPE_NMI_SOURCE 3 #define ACPI_MADT_TYPE_LOCAL_APIC_NMI 4 #define ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE 5 #define ACPI_MADT_TYPE_IO_SAPIC 6 #define ACPI_MADT_TYPE_LOCAL_SAPIC 7 #define ACPI_MADT_TYPE_INTERRUPT_SOURCE 8 #define ACPI_MADT_TYPE_LOCAL_X2APIC 9 #define ACPI_MADT_TYPE_LOCAL_X2APIC_NMI 10 #define ACPI_MADT_TYPE_GENERIC_INTERRUPT 11 #define ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR 12 #define ACPI_MADT_TYPE_GENERIC_MSI_FRAME 13 #define ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR 14 #define ACPI_MADT_TYPE_GENERIC_TRANSLATOR 15 #define ACPI_MADT_TYPE_MULTIPROC_WAKEUP 16 #define ACPI_MADT_TYPE_CORE_PIC 17 #define ACPI_MADT_TYPE_LIO_PIC 18 #define ACPI_MADT_TYPE_HT_PIC 19 #define ACPI_MADT_TYPE_EIO_PIC 20 #define ACPI_MADT_TYPE_MSI_PIC 21 #define ACPI_MADT_TYPE_BIO_PIC 22 #define ACPI_MADT_TYPE_LPC_PIC 23 #define ACPI_MADT_TYPE_RINTC 24 #define ACPI_MADT_TYPE_IMSIC 25 #define ACPI_MADT_TYPE_APLIC 26 #define ACPI_MADT_TYPE_PLIC 27 /* ACPI MADT Processor Local APIC Flags */ #define ACPI_MADT_PLACE_ENABLED 0 /* Processor Local APIC CPU Enabled */ #define ACPI_MADT_PLAOC_ENABLED 1 /* Processor Local APIC Online Capable */ /* ACPI Timer frequency */ #define ACPI_PM_TIMER_FREQUENCY 3579545 /* ACPI address space definitions */ #define ACPI_ADDRESS_SPACE_MEMORY 0x00 /* Maximum number of cached ACPI tables */ #define ACPI_MAX_CACHED_TABLES 32 /* Default serial port settings */ #define COMPORT_CLOCK_RATE 0x1C200 #define COMPORT_WAIT_TIMEOUT 204800 /* Serial port divisors */ #define COMPORT_DIV_DLL 0x00 /* Divisor Latch Least */ #define COMPORT_DIV_DLM 0x01 /* Divisor Latch Most */ /* Serial port control flags */ #define COMPORT_FLAG_INIT 0x01 /* Port Initialized */ #define COMPORT_FLAG_DBR 0x02 /* Default Baud Rate */ #define COMPORT_FLAG_MC 0x04 /* Modem Control */ /* Serial port Fifo Control Register (FCR) access masks */ #define COMPORT_FCR_DISABLE 0x00 /* Disable */ #define COMPORT_FCR_ENABLE 0x01 /* Enable */ #define COMPORT_FCR_RCVR_RESET 0x02 /* Receiver Reset */ #define COMPORT_FCR_TXMT_RESET 0x04 /* Transmitter Reset */ /* Serial port Line Control Register (LCR) access masks */ #define COMPORT_LCR_1STOP 0x00 /* 1 Stop Bit */ #define COMPORT_LCR_2STOP 0x04 /* 2 Stop Bits */ #define COMPORT_LCR_5DATA 0x00 /* 5 Data Bits */ #define COMPORT_LCR_6DATA 0x01 /* 6 Data Bits */ #define COMPORT_LCR_7DATA 0x02 /* 7 Data Bits */ #define COMPORT_LCR_8DATA 0x03 /* 8 Data Bits */ #define COMPORT_LCR_PARN 0x00 /* None Parity */ #define COMPORT_LCR_PARO 0x08 /* Odd Parity */ #define COMPORT_LCR_PARE 0x18 /* Even Parity */ #define COMPORT_LCR_PARM 0x28 /* Mark Parity */ #define COMPORT_LCR_PARS 0x38 /* Space Parity */ #define COMPORT_LCR_BREAK 0x40 /* Break */ #define COMPORT_LCR_DLAB 0x80 /* Divisor Latch Access Bit */ /* Serial port Line Status Register (LSR) access masks */ #define COMPORT_LSR_DIS 0x00 /* Disable */ #define COMPORT_LSR_DR 0x01 /* Data Ready */ #define COMPORT_LSR_OE 0x02 /* Overrun Error */ #define COMPORT_LSR_PE 0x04 /* Parity Error */ #define COMPORT_LSR_FE 0x08 /* Framing Error */ #define COMPORT_LSR_BI 0x10 /* Break Interrupt */ #define COMPORT_LSR_THRE 0x20 /* Transmit Holding Register Empty */ #define COMPORT_LSR_TEMPTY 0x40 /* Transmitter Empty */ #define COMPORT_LSR_FIFOE 0x80 /* FIFO Error */ /* Serial port Modem Control Register (MCR) access masks */ #define COMPORT_MCR_DTR 0x01 /* Data Terminal Ready */ #define COMPORT_MCR_RTS 0x02 /* Ready To Send */ #define COMPORT_MCR_OUT1 0x04 /* Generic Output 1 */ #define COMPORT_MCR_OUT2 0x08 /* Generic Output 2 */ #define COMPORT_MCR_NOM 0x0F /* Normal Operation Mode */ #define COMPORT_MCR_LOOP 0x10 /* Loopback Testing Mode */ /* Serial port Modem Status Register (MSR) access masks */ #define COMPORT_MSR_DCTS 0x01 /* Delta Clear To Send */ #define COMPORT_MSR_DDSR 0x02 /* Delta Data Set Ready */ #define COMPORT_MSR_DTRRTS 0x03 /* DTR and RTS */ #define COMPORT_MSR_TERI 0x04 /* Trailing Edge Ring Indicator */ #define COMPORT_MSR_DDCD 0x08 /* Delta Data Carrier Detect */ #define COMPORT_MSR_CTS 0x10 /* Clear To Send */ #define COMPORT_MSR_DSR 0x20 /* Data Set Ready */ #define COMPORT_MSR_RI 0x40 /* Ring Indicator */ #define COMPORT_MSR_DCD 0x80 /* Data Carrier Detect */ #define COMPORT_MSR_DSRCTSCD 0xB0 /* DSR, CTS and CD */ #define COMPORT_MSR_TST 0xAE /* Test Pattern */ /* Serial port offsets of the various registers */ #define COMPORT_REG_RBR 0x00 /* Receive Buffer Register */ #define COMPORT_REG_THR 0x00 /* Transmit Holding Register */ #define COMPORT_REG_IER 0x01 /* Interrupt Enable Register */ #define COMPORT_REG_IIR 0x02 /* Interrupt Identity Register */ #define COMPORT_REG_FCR 0x02 /* FIFO Control Register */ #define COMPORT_REG_LCR 0x03 /* Line Control Register */ #define COMPORT_REG_MCR 0x04 /* Modem Control Register */ #define COMPORT_REG_LSR 0x05 /* Line Status Register */ #define COMPORT_REG_MSR 0x06 /* Modem Status Register */ #define COMPORT_REG_SR 0x07 /* Scratch Register */ /* Standard system clock rates (in 100-nanosecond units)*/ #define HL_CLOCK_RATE_1000HZ 10000 /* 1 ms (1000 Hz) - Best Performance */ #define HL_CLOCK_RATE_500HZ 20000 /* 2 ms (500 Hz) - High Responsiveness */ #define HL_CLOCK_RATE_300HZ 33333 /* 3.33ms (300 Hz) - Multimedia Sync */ #define HL_CLOCK_RATE_250HZ 40000 /* 4 ms (250 Hz) - Optimal Balance */ #define HL_CLOCK_RATE_100HZ 100000 /* 10 ms (100 Hz) - Power Saving */ #define HL_CLOCK_RATE_50HZ 200000 /* 20 ms (50 Hz) - Deep Power Saving */ /* Minimum and maximum system clock rate definitions */ #define HL_MINIMUM_CLOCK_RATE HL_CLOCK_RATE_1000HZ #define HL_MAXIMUM_CLOCK_RATE HL_CLOCK_RATE_50HZ /* Minimum and maximum profile intervals */ #define MIN_PROFILE_INTERVAL 10000 #define MAX_PROFILE_INTERVAL 10000000 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Hardware Layer routine callbacks */ typedef XTSTATUS (XTAPI *PHALP_INITIALIZE_CLOCK)(VOID); typedef ULONGLONG (XTAPI *PHALP_QUERY_PERF_COUNTER)(VOID); typedef ULONG (XTAPI *PHALP_QUERY_TIME_DELTA)(VOID); typedef ULONG (XTAPI *PHALP_SET_CLOCK_RATE)(IN ULONG Increment); typedef VOID (XTAPI *PHALP_STALL_EXECUTION)(IN ULONG MicroSeconds); /* Generic Address structure */ typedef struct _GENERIC_ADDRESS { UCHAR AddressSpaceID; UCHAR BitWidth; UCHAR BitOffset; UCHAR Reserved; PHYSICAL_ADDRESS Address; } PACKED GENERIC_ADDRESS, *PGENERIC_ADDRESS; /* Each ACPI table description header structure */ typedef struct _ACPI_DESCRIPTION_HEADER { ULONG Signature; ULONG Length; UCHAR Revision; UCHAR Checksum; UCHAR OemId[6]; UCHAR OemTableID[8]; ULONG OemRevision; UCHAR CreatorID[4]; ULONG CreatorRev; } PACKED ACPI_DESCRIPTION_HEADER, *PACPI_DESCRIPTION_HEADER; /* Each ACPI subtable description header structure */ typedef struct _ACPI_SUBTABLE_HEADER { UCHAR Type; UCHAR Length; } PACKED ACPI_SUBTABLE_HEADER, *PACPI_SUBTABLE_HEADER; /* ACPI cache list structure */ typedef struct _ACPI_CACHE_LIST { LIST_ENTRY ListEntry; PACPI_DESCRIPTION_HEADER Table; } ACPI_CACHE_LIST, *PACPI_CACHE_LIST; /* ACPI Root System Description Table Pointer (RSDP) structure */ typedef struct _ACPI_RSDP { ULONGLONG Signature; UCHAR Checksum; UCHAR OemId[6]; UCHAR Revision; ULONG RsdtAddress; ULONG Length; ULONGLONG XsdtAddress; UCHAR XChecksum; UCHAR Reserved[3]; } PACKED ACPI_RSDP, *PACPI_RSDP; /* ACPI Root System Description Table (RSDT) structure */ typedef struct _ACPI_RSDT { ACPI_DESCRIPTION_HEADER Header; ULONG Tables[]; } PACKED ACPI_RSDT, *PACPI_RSDT; /* ACPI eXtended Root System Description Table (XSDT) structure */ typedef struct _ACPI_XSDT { ACPI_DESCRIPTION_HEADER Header; ULONGLONG Tables[]; } PACKED ACPI_XSDT, *PACPI_XSDT; /* Fixed ACPI Description Table (FADT) structure */ typedef struct _ACPI_FADT { ACPI_DESCRIPTION_HEADER Header; ULONG FirmwareCtrl; ULONG Dsdt; UCHAR IntModel; UCHAR PmProfile; USHORT SciIntVector; ULONG SmiCmdIoPort; UCHAR AcpiOnValue; UCHAR AcpiOffValue; UCHAR S4BiosReq; UCHAR PStateControl; ULONG Pm1aEvtBlkIoPort; ULONG Pm1bEvtBlkIoPort; ULONG Pm1aCtrlBlkIoPort; ULONG Pm1bCtrlBlkIoPort; ULONG Pm2CtrlBlkIoPort; ULONG PmTmrBlkIoPort; ULONG Gp0BlkIoPort; ULONG Gp1BlkIoPort; UCHAR Pm1EvtLen; UCHAR Pm1CtrlLen; UCHAR Pm2CtrlLen; UCHAR PmTmrLen; UCHAR Gp0BlkLen; UCHAR Gp1BlkLen; UCHAR Gp1Base; UCHAR CStateControl; USHORT Lvl2Latency; USHORT Lvl3Latency; USHORT FlushSize; USHORT FlushStride; UCHAR DutyOffset; UCHAR DutyWidth; UCHAR DayAlarmIndex; UCHAR MonthAlarmIndex; UCHAR CenturyAlarmIndex; USHORT BootArch; UCHAR Reserved0; ULONG Flags; GENERIC_ADDRESS ResetReg; UCHAR ResetVal; USHORT ArmBootArch; UCHAR Reserved1; PHYSICAL_ADDRESS XFirmwareCtrl; PHYSICAL_ADDRESS XDsdt; GENERIC_ADDRESS XPm1aEvtBlk; GENERIC_ADDRESS XPm1bEvtBlk; GENERIC_ADDRESS XPm1aCtrlBlk; GENERIC_ADDRESS XPm1bCtrlBlk; GENERIC_ADDRESS XPm2CtrlBlk; GENERIC_ADDRESS XPmTmrBlk; GENERIC_ADDRESS XGp0Blk; GENERIC_ADDRESS XGp1Blk; GENERIC_ADDRESS SleepControlReg; GENERIC_ADDRESS SleepStatusReg; } PACKED ACPI_FADT, *PACPI_FADT; /* ACPI High Precision Event Timer (HPET) table structure */ typedef struct _ACPI_HPET { ACPI_DESCRIPTION_HEADER Header; ULONG EventTimerBlockId; GENERIC_ADDRESS BaseAddress; UCHAR HpetNumber; USHORT MinimumTick; UCHAR PageProtectionAndOem; } PACKED ACPI_HPET, *PACPI_HPET; /* ACPI Multiple APIC Description Table (MADT) structure */ typedef struct _ACPI_MADT { ACPI_DESCRIPTION_HEADER Header; ULONG LocalApicAddress; ULONG Flags; ULONG ApicTables[]; } PACKED ACPI_MADT, *PACPI_MADT; /* ACPI Interrupt Override MADT subtable structure */ typedef struct _ACPI_MADT_INTERRUPT_OVERRIDE { ACPI_SUBTABLE_HEADER Header; UCHAR Bus; UCHAR SourceIrq; ULONG GlobalSystemInterrupt; USHORT Flags; } PACKED ACPI_MADT_INTERRUPT_OVERRIDE, *PACPI_MADT_INTERRUPT_OVERRIDE; /* ACPI IO APIC MADT subtable structure */ typedef struct _ACPI_MADT_IOAPIC { ACPI_SUBTABLE_HEADER Header; UCHAR IoApicId; UCHAR Reserved; ULONG IoApicAddress; ULONG GlobalIrqBase; } PACKED ACPI_MADT_IOAPIC, *PACPI_MADT_IOAPIC; /* ACPI Local APIC MADT subtable structure */ typedef struct _ACPI_MADT_LOCAL_APIC { ACPI_SUBTABLE_HEADER Header; UCHAR AcpiId; UCHAR ApicId; ULONG Flags; } PACKED ACPI_MADT_LOCAL_APIC, *PACPI_MADT_LOCAL_APIC; /* ACPI Local X2APIC MADT subtable structure */ typedef struct _ACPI_MADT_LOCAL_X2APIC { ACPI_SUBTABLE_HEADER Header; USHORT Reserved; ULONG ApicId; ULONG Flags; ULONG AcpiId; } PACKED ACPI_MADT_LOCAL_X2APIC, *PACPI_MADT_LOCAL_X2APIC; /* ACPI System Information structure */ typedef struct _ACPI_SYSTEM_INFO { ULONG CpuCount; ULONG RunningCpus; ULONG BusCount; ULONG IoApicCount; ULONG IntiCount; ULONG LintiCount; BOOLEAN ImcrPresent; ULONG ApicBase; PPROCESSOR_IDENTITY CpuInfo; ULONG IoApicPhysicalBase[APIC_MAX_IOAPICS]; ULONG IoApicVirtualBase[APIC_MAX_IOAPICS]; ULONG IoApicVectorBase[APIC_MAX_IOAPICS]; } ACPI_SYSTEM_INFO, *PACPI_SYSTEM_INFO; /* ACPI Timer information structure */ typedef struct _ACPI_TIMER_INFO { ULONG TimerPort; ULONG MsbMask; } ACPI_TIMER_INFO, *PACPI_TIMER_INFO; /* Serial (COM) port state */ typedef struct _CPPORT { PUCHAR Address; ULONG Baud; USHORT Flags; UCHAR Ring; } CPPORT, *PCPPORT; /* Framebuffer data structure */ typedef struct _HL_FRAMEBUFFER_DATA { BOOLEAN Initialized; PVOID Address; ULONG_PTR BufferSize; UINT Width; UINT Height; UINT PixelsPerScanLine; UINT BytesPerPixel; UINT Pitch; PVOID Font; struct { USHORT BlueShift; USHORT BlueSize; USHORT GreenShift; USHORT GreenSize; USHORT RedShift; USHORT RedSize; USHORT ReservedShift; USHORT ReservedSize; } Pixels; } HL_FRAMEBUFFER_DATA, *PHL_FRAMEBUFFER_DATA; /* Scroll region data structure */ typedef struct _HL_SCROLL_REGION_DATA { ULONG Left; ULONG Top; ULONG Right; ULONG Bottom; ULONG WidthInChars; ULONG HeightInChars; ULONG CursorX; ULONG CursorY; ULONG BackgroundColor; ULONG TextColor; } HL_SCROLL_REGION_DATA, *PHL_SCROLL_REGION_DATA; /* Processor identity structure */ typedef struct _PROCESSOR_IDENTITY { ULONG AcpiId; ULONG ApicId; USHORT CpuNumber; BOOLEAN Bsp; BOOLEAN Started; } PROCESSOR_IDENTITY, *PPROCESSOR_IDENTITY; /* SMBIOS table header structure */ typedef struct _SMBIOS_TABLE_HEADER { UCHAR Signature[4]; UCHAR Checksum; UCHAR Length; UCHAR MajorVersion; UCHAR MinorVersion; USHORT MaxStructureSize; UCHAR EntryPointRevision; UCHAR Reserved[5]; UCHAR Signature2[5]; UCHAR IntermediateChecksum; USHORT TableLength; ULONG TableAddress; USHORT NumberOfStructures; UCHAR BcdRevision; } SMBIOS_TABLE_HEADER, *PSMBIOS_TABLE_HEADER; /* SMBIOS3 table header structure */ typedef struct _SMBIOS3_TABLE_HEADER { UCHAR Signature[5]; UCHAR Checksum; UCHAR Length; UCHAR MajorVersion; UCHAR MinorVersion; UCHAR DocRevision; UCHAR EntryPointRevision; UCHAR Reserved; ULONG MaxStructureSize; ULONGLONG TableAddress; } SMBIOS3_TABLE_HEADER, *PSMBIOS3_TABLE_HEADER; /* Timer dispatch table */ typedef struct _TIMER_ROUTINES { PHALP_INITIALIZE_CLOCK InitializeClock; PHALP_QUERY_PERF_COUNTER QueryPerformanceCounter; PHALP_QUERY_TIME_DELTA QueryTimeDelta; PHALP_SET_CLOCK_RATE SetClockRate; PHALP_STALL_EXECUTION StallExecution; } TIMER_ROUTINES, *PTIMER_ROUTINES; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_HLTYPES_H */ ================================================ FILE: sdk/xtdk/i686/artypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/i686/artypes.h * DESCRIPTION: I686 architecture library structure definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_I686_ARTYPES_H #define __XTDK_I686_ARTYPES_H #include #include #include #include ARCH_HEADER(xtstruct.h) /* Control Register 0 constants */ #define CR0_PE 0x00000001 #define CR0_MP 0x00000002 #define CR0_EM 0x00000004 #define CR0_TS 0x00000008 #define CR0_ET 0x00000010 #define CR0_NE 0x00000020 #define CR0_WP 0x00010000 #define CR0_AM 0x00040000 #define CR0_NW 0x20000000 #define CR0_CD 0x40000000 #define CR0_PG 0x80000000 /* Control Register 4 constants */ #define CR4_VME 0x00000001 #define CR4_PVI 0x00000002 #define CR4_TSD 0x00000004 #define CR4_DE 0x00000008 #define CR4_PSE 0x00000010 #define CR4_PAE 0x00000020 #define CR4_MCE 0x00000040 #define CR4_PGE 0x00000080 #define CR4_PCE 0x00000100 #define CR4_FXSR 0x00000200 #define CR4_XMMEXCPT 0x00000400 #define CR4_UMIP 0x00000800 #define CR4_LA57 0x00001000 #define CR4_VMXE 0x00002000 #define CR4_SMXE 0x00004000 #define CR4_FSGSBASE 0x00010000 #define CR4_PCIDE 0x00020000 #define CR4_XSAVE 0x00040000 #define CR4_KL 0x00080000 #define CR4_SMEP 0x00100000 #define CR4_SMAP 0x00200000 #define CR4_PKE 0x00400000 #define CR4_CET 0x00800000 #define CR4_PKS 0x01000000 #define CR4_UINTR 0x02000000 #define CR4_LASS 0x08000000 #define CR4_LAM_SUP 0x10000000 /* Descriptors size */ #define GDT_ENTRIES 128 #define IDT_ENTRIES 256 /* Initial MXCSR control */ #define INITIAL_MXCSR 0x1F80 /* Segment defintions */ #define SEGMENT_CS 0x2E #define SEGMENT_DS 0x3E #define SEGMENT_ES 0x26 #define SEGMENT_SS 0x36 #define SEGMENT_FS 0x64 #define SEGMENT_GS 0x65 /* X86 EFLAG bit masks definitions */ #define X86_EFLAGS_NF_MASK 0x00000000 /* None */ #define X86_EFLAGS_CF_MASK 0x00000001 /* Carry */ #define X86_EFLAGS_PF_MASK 0x00000004 /* Parity */ #define X86_EFALGS_AF_MASK 0x00000010 /* Aux Carry */ #define X86_EFLAGS_ZF_MASK 0x00000040 /* Zero */ #define X86_EFLAGS_SF_MASK 0x00000080 /* Sign */ #define X86_EFLAGS_TF_MASK 0x00000100 /* Trap */ #define X86_EFLAGS_IF_MASK 0x00000200 /* Interrupt */ #define X86_EFLAGS_DF_MASK 0x00000400 /* Direction */ #define X86_EFLAGS_OF_MASK 0x00000800 /* Overflow */ #define X86_EFLAGS_IOPL_MASK 0x00003000 /* I/O Privilege */ #define X86_EFLAGS_NT_MASK 0x00004000 /* Nested Task */ #define X86_EFLAGS_SIGN_MASK 0x00008000 /* Sign */ #define X86_EFLAGS_RF_MASK 0x00010000 /* Resume */ #define X86_EFLAGS_V86_MASK 0x00020000 /* Virtual 8086 */ #define X86_EFLAGS_AC_MASK 0x00040000 /* Alignment Check */ #define X86_EFLAGS_VIF_MASK 0x00080000 /* Virtual Interrupt */ #define X86_EFLAGS_VIP_MASK 0x00100000 /* Virtual Interrupt Pending */ #define X86_EFLAGS_ID_MASK 0x00200000 /* Identification */ /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* CPU vendor enumeration list */ typedef enum _CPU_VENDOR { CPU_VENDOR_AMD = 0x68747541, CPU_VENDOR_INTEL = 0x756e6547, CPU_VENDOR_UNKNOWN = 0xFFFFFFFF } CPU_VENDOR, *PCPU_VENDOR; /* CPUID advanced power management features (0x80000007) enumeration list */ typedef enum _CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT { CPUID_FEATURES_EDX_TS = 1 << 0, /* Temperature Sensor */ CPUID_FEATURES_EDX_FIS = 1 << 1, /* Frequency ID Selection */ CPUID_FEATURES_EDX_VIS = 1 << 2, /* Voltage ID Selection */ CPUID_FEATURES_EDX_TTS = 1 << 3, /* ThermaTrip Support */ CPUID_FEATURES_EDX_HTC = 1 << 4, /* Hardware Thermal Throttling */ CPUID_FEATURES_EDX_STC = 1 << 5, /* Software Thermal Throttling */ CPUID_FEATURES_EDX_TSCI = 1 << 8 /* TSC Invariant */ } CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT, *PCPUID_FEATURES_ADVANCED_POWER_MANAGEMENT; /* CPUID extended features (0x80000001) enumeration list */ typedef enum _CPUID_FEATURES_EXTENDED { CPUID_FEATURES_ECX_LAHF_SAHF = 1 << 0, CPUID_FEATURES_ECX_CMP_LEGACY = 1 << 1, CPUID_FEATURES_ECX_SVM = 1 << 2, CPUID_FEATURES_ECX_EXT_APIC_SPACE = 1 << 3, CPUID_FEATURES_ECX_ALT_MOV_CR8 = 1 << 4, CPUID_FEATURES_ECX_LZCNT = 1 << 5, CPUID_FEATURES_ECX_SSE4A = 1 << 6, CPUID_FEATURES_ECX_MISALIGNED_SSE = 1 << 7, CPUID_FEATURES_ECX_PREFETCHW = 1 << 8, CPUID_FEATURES_ECX_OSVW = 1 << 9, CPUID_FEATURES_ECX_IBS = 1 << 10, CPUID_FEATURES_ECX_XOP = 1 << 11, CPUID_FEATURES_ECX_SKINIT = 1 << 12, CPUID_FEATURES_ECX_WDT = 1 << 13, CPUID_FEATURES_ECX_LWP = 1 << 15, CPUID_FEATURES_ECX_FMA4 = 1 << 16, CPUID_FEATURES_ECX_TCE = 1 << 17, CPUID_FEATURES_ECX_NODEID = 1 << 19, CPUID_FEATURES_ECX_TBM = 1 << 21, CPUID_FEATURES_ECX_TOPOLOGY_EXTENSIONS = 1 << 22, CPUID_FEATURES_ECX_PERFCTR_EXT_CORE = 1 << 23, CPUID_FEATURES_ECX_PERFCTR_EXT_NB = 1 << 24, CPUID_FEATURES_ECX_DATA_BREAKPOINT_EXT = 1 << 26, CPUID_FEATURES_ECX_PERF_TSC = 1 << 27, CPUID_FEATURES_ECX_PERFCTR_EXT_L2I = 1 << 28, CPUID_FEATURES_ECX_MONITORX_MWAITX = 1 << 29, CPUID_FEATURES_ECX_CODEBP_ADDRMASK_EXT = 1 << 30, CPUID_FEATURES_EDX_SYSCALL_SYSRET = 1 << 11, CPUID_FEATURES_EDX_NX = 1 << 20, CPUID_FEATURES_EDX_AMD_MMX_EXT = 1 << 22, CPUID_FEATURES_EDX_FFXSR = 1 << 25, CPUID_FEATURES_EDX_1G_PAGES = 1 << 26, CPUID_FEATURES_EDX_RDTSCP = 1 << 27, CPUID_FEATURES_EDX_LONG_MODE = 1 << 29, CPUID_FEATURES_EDX_3DNOW_EXT = 1 << 30, CPUID_FEATURES_EDX_3DNOW = 1 << 31 } CPUID_FEATURES_EXTENDED, *PCPUID_FEATURES_EXTENDED; /* CPUID Thermal and Power Management features (0x00000006) enumeration list */ typedef enum _CPUID_FEATURES_POWER_MANAGEMENT { CPUID_FEATURES_EAX_DTHERM = 1 << 0, CPUID_FEATURES_EAX_IDA = 1 << 1, CPUID_FEATURES_EAX_ARAT = 1 << 2, CPUID_FEATURES_EAX_PLN = 1 << 4, CPUID_FEATURES_EAX_PTS = 1 << 6, CPUID_FEATURES_EAX_HWP = 1 << 7, CPUID_FEATURES_EAX_HWP_NOTIFY = 1 << 8, CPUID_FEATURES_EAX_HWP_ACT_WINDOW = 1 << 9, CPUID_FEATURES_EAX_HWP_EPP = 1 << 10, CPUID_FEATURES_EAX_HWP_PKG_REQ = 1 << 11, CPUID_FEATURES_EAX_HWP_HIGHEST_PERF_CHANGE = 1 << 15, CPUID_FEATURES_EAX_HFI = 1 << 19 } CPUID_FEATURES_LEAF6, *PCPUID_FEATURES_LEAF6; /* CPUID STD1 features (0x00000001) enumeration list */ typedef enum _CPUID_FEATURES_STANDARD1 { CPUID_FEATURES_ECX_SSE3 = 1 << 0, CPUID_FEATURES_ECX_PCLMUL = 1 << 1, CPUID_FEATURES_ECX_DTES64 = 1 << 2, CPUID_FEATURES_ECX_MONITOR = 1 << 3, CPUID_FEATURES_ECX_DS_CPL = 1 << 4, CPUID_FEATURES_ECX_VMX = 1 << 5, CPUID_FEATURES_ECX_SMX = 1 << 6, CPUID_FEATURES_ECX_EST = 1 << 7, CPUID_FEATURES_ECX_TM2 = 1 << 8, CPUID_FEATURES_ECX_SSSE3 = 1 << 9, CPUID_FEATURES_ECX_CID = 1 << 10, CPUID_FEATURES_ECX_SDBG = 1 << 11, CPUID_FEATURES_ECX_FMA = 1 << 12, CPUID_FEATURES_ECX_CX16 = 1 << 13, CPUID_FEATURES_ECX_XTPR = 1 << 14, CPUID_FEATURES_ECX_PDCM = 1 << 15, CPUID_FEATURES_ECX_PCID = 1 << 17, CPUID_FEATURES_ECX_DCA = 1 << 18, CPUID_FEATURES_ECX_SSE4_1 = 1 << 19, CPUID_FEATURES_ECX_SSE4_2 = 1 << 20, CPUID_FEATURES_ECX_X2APIC = 1 << 21, CPUID_FEATURES_ECX_MOVBE = 1 << 22, CPUID_FEATURES_ECX_POPCNT = 1 << 23, CPUID_FEATURES_ECX_TSC_DEADLINE = 1 << 24, CPUID_FEATURES_ECX_AES = 1 << 25, CPUID_FEATURES_ECX_XSAVE = 1 << 26, CPUID_FEATURES_ECX_OSXSAVE = 1 << 27, CPUID_FEATURES_ECX_AVX = 1 << 28, CPUID_FEATURES_ECX_F16C = 1 << 29, CPUID_FEATURES_ECX_RDRAND = 1 << 30, CPUID_FEATURES_ECX_HYPERVISOR = 1 << 31, CPUID_FEATURES_EDX_FPU = 1 << 0, CPUID_FEATURES_EDX_VME = 1 << 1, CPUID_FEATURES_EDX_DE = 1 << 2, CPUID_FEATURES_EDX_PSE = 1 << 3, CPUID_FEATURES_EDX_TSC = 1 << 4, CPUID_FEATURES_EDX_MSR = 1 << 5, CPUID_FEATURES_EDX_PAE = 1 << 6, CPUID_FEATURES_EDX_MCE = 1 << 7, CPUID_FEATURES_EDX_CX8 = 1 << 8, CPUID_FEATURES_EDX_APIC = 1 << 9, CPUID_FEATURES_EDX_SEP = 1 << 11, CPUID_FEATURES_EDX_MTRR = 1 << 12, CPUID_FEATURES_EDX_PGE = 1 << 13, CPUID_FEATURES_EDX_MCA = 1 << 14, CPUID_FEATURES_EDX_CMOV = 1 << 15, CPUID_FEATURES_EDX_PAT = 1 << 16, CPUID_FEATURES_EDX_PSE36 = 1 << 17, CPUID_FEATURES_EDX_PSN = 1 << 18, CPUID_FEATURES_EDX_CLFLUSH = 1 << 19, CPUID_FEATURES_EDX_DS = 1 << 21, CPUID_FEATURES_EDX_ACPI = 1 << 22, CPUID_FEATURES_EDX_MMX = 1 << 23, CPUID_FEATURES_EDX_FXSR = 1 << 24, CPUID_FEATURES_EDX_SSE = 1 << 25, CPUID_FEATURES_EDX_SSE2 = 1 << 26, CPUID_FEATURES_EDX_SS = 1 << 27, CPUID_FEATURES_EDX_HTT = 1 << 28, CPUID_FEATURES_EDX_TM = 1 << 29, CPUID_FEATURES_EDX_IA64 = 1 << 30, CPUID_FEATURES_EDX_PBE = 1 << 31 } CPUID_FEATURES_STANDARD1, *PCPUID_FEATURES_STANDARD1; /* CPUID STD7 features (0x00000007, subleaf 0) enumeration list */ typedef enum _CPUID_FEATURES_STANDARD7_LEAF0 { CPUID_FEATURES_EBX_FSGSBASE = 1 << 0, CPUID_FEATURES_EBX_TSC_ADJUST = 1 << 1, CPUID_FEATURES_EBX_SGX = 1 << 2, CPUID_FEATURES_EBX_BMI1 = 1 << 3, CPUID_FEATURES_EBX_HLE = 1 << 4, CPUID_FEATURES_EBX_AVX2 = 1 << 5, CPUID_FEATURES_EBX_FDP_DEPRECATION = 1 << 6, CPUID_FEATURES_EBX_SMEP = 1 << 7, CPUID_FEATURES_EBX_BMI2 = 1 << 8, CPUID_FEATURES_EBX_ERMS = 1 << 9, CPUID_FEATURES_EBX_INVPCID = 1 << 10, CPUID_FEATURES_EBX_RTM = 1 << 11, CPUID_FEATURES_EBX_QOS_MONITORING = 1 << 12, CPUID_FEATURES_EBX_DEPRECATE_FCS_FDS = 1 << 13, CPUID_FEATURES_EBX_MPX = 1 << 14, CPUID_FEATURES_EBX_QOS_ENFORCEMENT = 1 << 15, CPUID_FEATURES_EBX_AVX512F = 1 << 16, CPUID_FEATURES_EBX_AVX512DQ = 1 << 17, CPUID_FEATURES_EBX_RDSEED = 1 << 18, CPUID_FEATURES_EBX_ADX = 1 << 19, CPUID_FEATURES_EBX_SMAP = 1 << 20, CPUID_FEATURES_EBX_AVX512IFMA52 = 1 << 21, CPUID_FEATURES_EBX_CLFLUSHOPT = 1 << 23, CPUID_FEATURES_EBX_CLWB = 1 << 24, CPUID_FEATURES_EBX_PROCESSOR_TRACE = 1 << 25, CPUID_FEATURES_EBX_AVX512PF = 1 << 26, CPUID_FEATURES_EBX_AVX512ER = 1 << 27, CPUID_FEATURES_EBX_AVX512CD = 1 << 28, CPUID_FEATURES_EBX_SHA = 1 << 29, CPUID_FEATURES_EBX_AVX512BW = 1 << 30, CPUID_FEATURES_EBX_AVX512VL = 1 << 31, CPUID_FEATURES_ECX_PREFETCHWT1 = 1 << 0, CPUID_FEATURES_ECX_AVX512_VBMI = 1 << 1, CPUID_FEATURES_ECX_UMIP = 1 << 2, CPUID_FEATURES_ECX_PKU = 1 << 3, CPUID_FEATURES_ECX_OSPKE = 1 << 4, CPUID_FEATURES_ECX_WAITPKG = 1 << 5, CPUID_FEATURES_ECX_AVX512_VBMI2 = 1 << 6, CPUID_FEATURES_ECX_CET_SS = 1 << 7, CPUID_FEATURES_ECX_GFNI = 1 << 8, CPUID_FEATURES_ECX_VAES = 1 << 9, CPUID_FEATURES_ECX_VPCLMULQDQ = 1 << 10, CPUID_FEATURES_ECX_AVX512_VNNI = 1 << 11, CPUID_FEATURES_ECX_AVX512_BITALG = 1 << 12, CPUID_FEATURES_ECX_TME = 1 << 13, CPUID_FEATURES_ECX_AVX512_VPOPCNTDQ = 1 << 14, CPUID_FEATURES_ECX_LA57 = 1 << 16, CPUID_FEATURES_ECX_RDPID = 1 << 22, CPUID_FEATURES_ECX_KEYLOCKER = 1 << 23, CPUID_FEATURES_ECX_BUS_LOCK_DETECT = 1 << 24, CPUID_FEATURES_ECX_CLDEMOTE = 1 << 25, CPUID_FEATURES_ECX_MOVDIRI = 1 << 27, CPUID_FEATURES_ECX_MOVDIR64B = 1 << 28, CPUID_FEATURES_ECX_ENQCMD = 1 << 29, CPUID_FEATURES_ECX_SGX_LAUNCH_CONFIG = 1 << 30, CPUID_FEATURES_ECX_PKS = 1 << 31, CPUID_FEATURES_EDX_SGX_KEYS = 1 << 1, CPUID_FEATURES_EDX_AVX512_4VNNIW = 1 << 2, CPUID_FEATURES_EDX_AVX512_4FMAPS = 1 << 3, CPUID_FEATURES_EDX_FAST_SHORT_REP_MOV = 1 << 4, CPUID_FEATURES_EDX_UINTR = 1 << 5, CPUID_FEATURES_EDX_AVX512_VPINTERSECT = 1 << 8, CPUID_FEATURES_EDX_SRBDS_CTRL = 1 << 9, CPUID_FEATURES_EDX_MD_CLEAR = 1 << 10, CPUID_FEATURES_EDX_RTM_ALWAYS_ABORT = 1 << 11, CPUID_FEATURES_EDX_RTM_FORCE_ABORT = 1 << 13, CPUID_FEATURES_EDX_SERIALIZE = 1 << 14, CPUID_FEATURES_EDX_HYBRID = 1 << 15, CPUID_FEATURES_EDX_TSXLDTRK = 1 << 16, CPUID_FEATURES_EDX_PCONFIG = 1 << 18, CPUID_FEATURES_EDX_ARCH_LBR = 1 << 19, CPUID_FEATURES_EDX_CET_IBT = 1 << 20, CPUID_FEATURES_EDX_AMX_BF16 = 1 << 22, CPUID_FEATURES_EDX_AVX512_FP16 = 1 << 23, CPUID_FEATURES_EDX_AMX_TILE = 1 << 24, CPUID_FEATURES_EDX_AMX_INT8 = 1 << 25, CPUID_FEATURES_EDX_SCA_IBRS_IBPB = 1 << 26, CPUID_FEATURES_EDX_SCA_STIBP = 1 << 27, CPUID_FEATURES_EDX_L1D_FLUSH = 1 << 28, CPUID_FEATURES_EDX_ARCH_CAPABILITIES_MSR = 1 << 29, CPUID_FEATURES_EDX_CORE_CAPABILITIES_MSR = 1 << 30, CPUID_FEATURES_EDX_SCA_SSBD = 1 << 31 } CPUID_FEATURES_STANDARD7_LEAF0, *PCPUID_FEATURES_STANDARD7_LEAF0; /* CPUID STD7 features (0x00000007, subleaf 1) enumeration list */ typedef enum _CPUID_FEATURES_STANDARD7_LEAF1 { CPUID_FEATURES_EAX_SHA512 = 1 << 0, CPUID_FEATURES_EAX_SM3 = 1 << 1, CPUID_FEATURES_EAX_SM4 = 1 << 2, CPUID_FEATURES_EAX_RAO_INT = 1 << 3, CPUID_FEATURES_EAX_AVX_VNNI = 1 << 4, CPUID_FEATURES_EAX_AVX512_BF16 = 1 << 5, CPUID_FEATURES_EAX_LASS = 1 << 6, CPUID_FEATURES_EAX_CMPCCXADD = 1 << 7, CPUID_FEATURES_EAX_ARCH_PERFMON = 1 << 8, CPUID_FEATURES_EAX_FAST_ZEROLEN_REP_MOVSB = 1 << 10, CPUID_FEATURES_EAX_FAST_ZEROLEN_REP_STOSB = 1 << 11, CPUID_FEATURES_EAX_FAST_ZEROLEN_REP_CMPSB = 1 << 12, CPUID_FEATURES_EAX_FRED = 1 << 17, CPUID_FEATURES_EAX_LKGS = 1 << 18, CPUID_FEATURES_EAX_WRMSRNS = 1 << 19, CPUID_FEATURES_EAX_NMI_SOURCE_REPORTING = 1 << 20, CPUID_FEATURES_EAX_AMX_FP16 = 1 << 21, CPUID_FEATURES_EAX_HRESET = 1 << 22, CPUID_FEATURES_EAX_AVX_IFMA = 1 << 23, CPUID_FEATURES_EAX_LAM = 1 << 26, CPUID_FEATURES_EAX_MSRLIST = 1 << 27, CPUID_FEATURES_EAX_INVD_DISABLE = 1 << 30, CPUID_FEATURES_EAX_MOVRS = 1 << 31, CPUID_FEATURES_EBX_PPIN = 1 << 0, CPUID_FEATURES_EBX_TSE = 1 << 1, CPUID_FEATURES_EBX_CPUIDMAXVAL_LIM_RMV = 1 << 3, CPUID_FEATURES_ECX_MSR_IMM = 1 << 5, CPUID_FEATURES_EDX_AVX_VNNI_INT8 = 1 << 4, CPUID_FEATURES_EDX_AVX_NE_CONVERT = 1 << 5, CPUID_FEATURES_EDX_AMX_COMPLEX = 1 << 8, CPUID_FEATURES_EDX_AVX_VNNI_INT16 = 1 << 10, CPUID_FEATURES_EDX_USER_TIMER = 1 << 13, CPUID_FEATURES_EDX_PREFETCHI = 1 << 14, CPUID_FEATURES_EDX_USER_MSR = 1 << 15, CPUID_FEATURES_EDX_UIRET_UIF = 1 << 17, CPUID_FEATURES_EDX_CET_SSS = 1 << 18, CPUID_FEATURES_EDX_AVX10 = 1 << 19, CPUID_FEATURES_EDX_APX = 1 << 21, CPUID_FEATURES_EDX_MWAIT_AND_LEAF5 = 1 << 23 } CPUID_FEATURES_STANDARD7_LEAF1, *PCPUID_FEATURES_STANDARD7_LEAF1; /* CPUID requests */ typedef enum _CPUID_REQUESTS { CPUID_GET_VENDOR_STRING = 0x00000000, CPUID_GET_STANDARD1_FEATURES = 0x00000001, CPUID_GET_TLB_CACHE = 0x00000002, CPUID_GET_SERIAL = 0x00000003, CPUID_GET_CACHE_TOPOLOGY = 0x00000004, CPUID_GET_MONITOR_MWAIT = 0x00000005, CPUID_GET_POWER_MANAGEMENT = 0x00000006, CPUID_GET_STANDARD7_FEATURES = 0x00000007, CPUID_GET_TSC_CRYSTAL_CLOCK = 0x00000015, CPUID_GET_EXTENDED_MAX = 0x80000000, CPUID_GET_EXTENDED_FEATURES = 0x80000001, CPUID_GET_ADVANCED_POWER_MANAGEMENT = 0x80000007 } CPUID_REQUESTS, *PCPUID_REQUESTS; /* Interrupt handler */ typedef VOID (*PINTERRUPT_HANDLER)(PKTRAP_FRAME TrapFrame); /* Processor identification information */ typedef struct _CPU_IDENTIFICATION { ULONGLONG ExtendedFeatureBits; USHORT Family; ULONGLONG FeatureBits; USHORT Model; USHORT Stepping; CPU_VENDOR Vendor; UCHAR VendorName[13]; } CPU_IDENTIFICATION, *PCPU_IDENTIFICATION; /* CPUID registers */ typedef struct _CPUID_REGISTERS { UINT32 Leaf; UINT32 SubLeaf; UINT32 Eax; UINT32 Ebx; UINT32 Ecx; UINT32 Edx; } CPUID_REGISTERS, *PCPUID_REGISTERS; /* CPU signature read from CPUID structure definition */ typedef struct _CPUID_SIGNATURE { ULONG Stepping:4; ULONG Model:4; ULONG Family:4; ULONG Unused1:4; ULONG ExtendedModel:4; ULONG ExtendedFamily:8; ULONG Unused2:4; } CPU_SIGNATURE, *PCPU_SIGNATURE; /* Trampoline types */ typedef enum _TRAMPOLINE_TYPE { TrampolineApStartup } TRAMPOLINE_TYPE, *PTRAMPOLINE_TYPE; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_I686_ARTYPES_H */ ================================================ FILE: sdk/xtdk/i686/hlfuncs.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/i686/hlfuncs.h * DESCRIPTION: XT hardware abstraction layer routines specific to i686 architecture * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_I686_HLFUNCS_H #define __XTDK_I686_HLFUNCS_H #include #include #include #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Hardware layer routines forward references */ XTCLINK XTCDECL UCHAR HlReadPort8(IN USHORT Port); XTCLINK XTCDECL USHORT HlReadPort16(IN USHORT Port); XTCLINK XTCDECL ULONG HlReadPort32(IN USHORT Port); XTCLINK XTCDECL VOID HlWritePort8(IN USHORT Port, IN UCHAR Data); XTCLINK XTCDECL VOID HlWritePort16(IN USHORT Port, IN USHORT Value); XTCLINK XTCDECL VOID HlWritePort32(IN USHORT Port, IN ULONG Value); #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_I686_HLFUNCS_H */ ================================================ FILE: sdk/xtdk/i686/hltypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/i686/hltypes.h * DESCRIPTION: XT hardware abstraction layer structures definitions specific to i686 architecture * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_I686_HLTYPES_H #define __XTDK_I686_HLTYPES_H #include #include #include #include #include ARCH_HEADER(xtstruct.h) /* APIC base addresses */ #define APIC_BASE 0xFFFE0000 #define APIC_LAPIC_MSR_BASE 0x0000001B #define APIC_X2APIC_MSR_BASE 0x00000800 /* APIC vector definitions */ #define APIC_VECTOR_ZERO 0x00 #define APIC_VECTOR_SPURIOUS 0x1F #define APIC_VECTOR_APC 0x3D #define APIC_VECTOR_DPC 0x41 #define APIC_VECTOR_REBOOT 0x50 #define APIC_VECTOR_DEVICE1 0x51 #define APIC_VECTOR_DEVICE2 0x61 #define APIC_VECTOR_DEVICE3 0x71 #define APIC_VECTOR_DEVICE4 0x81 #define APIC_VECTOR_DEVICE5 0x91 #define APIC_VECTOR_DEVICE6 0xA1 #define APIC_VECTOR_DEVICE7 0xB1 #define APIC_VECTOR_GENERIC 0xC1 #define APIC_VECTOR_SYNC 0xC1 #define APIC_VECTOR_CLOCK 0xD1 #define APIC_VECTOR_CLOCK_IPI 0xD2 #define APIC_VECTOR_IPI 0xE1 #define APIC_VECTOR_ERROR 0xE3 #define APIC_VECTOR_POWERFAIL 0xEF #define APIC_VECTOR_PROFILE 0xFD #define APIC_VECTOR_PERF 0xFE #define APIC_VECTOR_NMI 0xFF /* APIC destination formats */ #define APIC_DF_FLAT 0xFFFFFFFF #define APIC_DF_CLUSTER 0x0FFFFFFF /* APIC trigger modes */ #define APIC_TGM_EDGE 0 #define APIC_TGM_LEVEL 1 /* APIC LDR (Logical Destination Register) shifts */ #define APIC_X2APIC_LDR_SHIFT 16 #define APIC_XAPIC_LDR_SHIFT 24 /* Maximum number of I/O APICs */ #define APIC_MAX_IOAPICS 64 /* I/O APIC base address */ #define IOAPIC_DEFAULT_BASE 0xFEC00000 /* I/O APIC definitions */ #define IOAPIC_MAX_CONTROLLERS 64 #define IOAPIC_MAX_OVERRIDES 16 #define IOAPIC_RTE_MASKED 0x100FF #define IOAPIC_RTE_SIZE 2 #define IOAPIC_VECTOR_FREE 0xFF #define IOAPIC_VECTOR_RESERVED 0xFE /* IOAPIC offsets */ #define IOAPIC_IOREGSEL 0x00 #define IOAPIC_IOWIN 0x10 /* IOAPIC registers */ #define IOAPIC_ID 0x00 #define IOAPIC_VER 0x01 #define IOAPIC_ARB 0x02 #define IOAPIC_REDTBL 0x10 /* 8259/ISP PIC ports definitions */ #define PIC1_CONTROL_PORT 0x20 #define PIC1_DATA_PORT 0x21 #define PIC1_ELCR_PORT 0x04D0 #define PIC2_CONTROL_PORT 0xA0 #define PIC2_DATA_PORT 0xA1 #define PIC2_ELCR_PORT 0x04D1 /* PIC vector definitions */ #define PIC1_VECTOR_SPURIOUS 0x37 /* HPET General Capabilities definitions */ #define HPET_CAPABILITY_64BIT 0x2000ULL #define HPET_CAPABILITY_LEGACY_REPLACEMENT 0x8000ULL /* HPET General Configuration definitions */ #define HPET_CONFIG_ENABLE 0x0001ULL #define HPET_CONFIG_LEGACY_REPLACEMENT 0x0002ULL /* HPET Timer Configuration definitions */ #define HPET_TIMER_CONFIG_LEVEL_TRIGGERED 0x0002ULL #define HPET_TIMER_CONFIG_ENABLED 0x0004ULL #define HPET_TIMER_CONFIG_PERIODIC 0x0008ULL #define HPET_TIMER_CONFIG_SUPPORTS_PERIODIC 0x0010ULL #define HPET_TIMER_CONFIG_SUPPORTS_64BIT 0x0020ULL #define HPET_TIMER_CONFIG_VALUE_ACCUMULATOR 0x0040ULL #define HPET_TIMER_CONFIG_FORCE_32BIT 0x0100ULL #define HPET_TIMER_CONFIG_FSB_ENABLED 0x4000ULL #define HPET_TIMER_CONFIG_SUPPORTS_FSB 0x8000ULL /* PIT ports definitions */ #define PIT_COMMAND_PORT 0x43 #define PIT_DATA_PORT0 0x40 #define PIT_DATA_PORT1 0x41 #define PIT_DATA_PORT2 0x42 /* PIT related definitions */ #define PIT_BASE_FREQUENCY 1193182 /* PIT Access Mode: Defines how the CPU reads or writes the counter value */ #define PIT_CMD_ACCESS_LATCH 0x00 #define PIT_CMD_ACCESS_LOWBYTE_ONLY 0x10 #define PIT_CMD_ACCESS_HIGHBYTE_ONLY 0x20 #define PIT_CMD_ACCESS_LOWBYTE_HIGHBYTE 0x30 /* PIT Channel Selection: Specifies the physical timer channel to configure */ #define PIT_CMD_CHANNEL0 0x00 #define PIT_CMD_CHANNEL1 0x40 #define PIT_CMD_CHANNEL2 0x80 /* PIT Operating Mode: Defines the hardware behavior and the generated waveform */ #define PIT_MODE0_INT_ON_TERMINAL_COUNT 0x00 #define PIT_MODE1_ONESHOT 0x02 #define PIT_MODE2_RATE_GENERATOR 0x04 #define PIT_MODE3_SQUARE_WAVE_GEN 0x06 #define PIT_MODE4_SOFTWARE_STROBE 0x08 #define PIT_MODE5_HARDWARE_STROBE 0x0A /* CMOS controller access ports */ #define CMOS_SELECT_PORT 0x70 #define CMOS_DATA_PORT 0x71 /* CMOD Select port definitions */ #define CMOS_NMI_SELECT 0x80 #define CMOS_REGISTER_SECOND 0x00 #define CMOS_REGISTER_MINUTE 0x02 #define CMOS_REGISTER_HOUR 0x04 #define CMOS_REGISTER_WEEKDAY 0x06 #define CMOS_REGISTER_DAY 0x07 #define CMOS_REGISTER_MONTH 0x08 #define CMOS_REGISTER_YEAR 0x09 #define CMOS_REGISTER_A 0x0A #define CMOS_REGISTER_B 0x0B #define CMOS_REGISTER_C 0x0C /* CMOS Register A definitions */ #define CMOS_REGISTER_A_RATE_MASK 0x0F #define CMOS_REGISTER_A_UPDATE_IN_PROGRESS 0x80 /* CMOS Register B definitions */ #define CMOS_REGISTER_B_24_HOUR 0x02 #define CMOS_REGISTER_B_BINARY 0x04 #define CMOS_REGISTER_B_PERIODIC 0x40 #define CMOS_REGISTER_B_SET_CLOCK 0x80 /* CMOS Register C definitions */ #define CMOS_REGISTER_C_PERIODIC 0x40 #define CMOS_REGISTER_C_INTERRUPT 0x80 /* CMOS RTC 24-hour mode */ #define CMOS_RTC_POST_MERIDIEM 0x80 /* Serial ports information */ #define COMPORT_ADDRESS {0x3F8, 0x2F8, 0x3E8, 0x2E8, 0x5F8, 0x4F8, 0x5E8, 0x4E8} #define COMPORT_COUNT 8 /* Initial stall factor */ #define INITIAL_STALL_FACTOR 100 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* APIC destination mode enumeration list */ typedef enum _APIC_DEST_MODE { APIC_DM_Physical, APIC_DM_Logical } APIC_DEST_MODE, *PAPIC_DEST_MODE; /* APIC delivery mode enumeration list */ typedef enum _APIC_DM { APIC_DM_FIXED, APIC_DM_LOWPRIO, APIC_DM_SMI, APIC_DM_REMOTE, APIC_DM_NMI, APIC_DM_INIT, APIC_DM_STARTUP, APIC_DM_EXTINT, } APIC_DM, *PAPIC_DM; /* APIC destination short-hand enumeration list */ typedef enum _APIC_DSH { APIC_DSH_Destination, APIC_DSH_Self, APIC_DSH_AllIncludingSelf, APIC_DSH_AllExclusingSelf } APIC_DSH, *PAPIC_DSH; /* APIC mode list */ typedef enum _APIC_MODE { APIC_MODE_COMPAT, APIC_MODE_X2APIC } APIC_MODE, *PAPIC_MODE; /* APIC Register Address Map */ typedef enum _APIC_REGISTER { APIC_ID = 0x02, /* APIC ID Register */ APIC_VER = 0x03, /* APIC Version Register */ APIC_TPR = 0x08, /* Task Priority Register */ APIC_APR = 0x09, /* Arbitration Priority Register */ APIC_PPR = 0x0A, /* Processor Priority Register (R) */ APIC_EOI = 0x0B, /* EOI Register */ APIC_RRR = 0x0C, /* Remote Read Register */ APIC_LDR = 0x0D, /* Logical Destination Register */ APIC_DFR = 0x0E, /* Destination Format Register (not available in extended mode) */ APIC_SIVR = 0x0F, /* Spurious Interrupt Vector Register */ APIC_ISR = 0x10, /* Interrupt Service Register*/ APIC_TMR = 0x18, /* Trigger Mode Register */ APIC_IRR = 0x20, /* Interrupt Request Register */ APIC_ESR = 0x28, /* Error Status Register */ APIC_ICR0 = 0x30, /* Interrupt Command Register */ APIC_ICR1 = 0x31, /* Interrupt Command Register (not available in extended mode) */ APIC_TMRLVTR = 0x32, /* Timer Local Vector Table */ APIC_THRMLVTR = 0x33, /* Thermal Local Vector Table */ APIC_PCLVTR = 0x34, /* Performance Counter Local Vector Table */ APIC_LINT0 = 0x35, /* LINT0 Local Vector Table */ APIC_LINT1 = 0x36, /* LINT1 Local Vector Table */ APIC_ERRLVTR = 0x37, /* Error Local Vector Table */ APIC_TICR = 0x38, /* Initial Count Register for Timer */ APIC_TCCR = 0x39, /* Current Count Register for Timer */ APIC_TDCR = 0x3E, /* Timer Divide Configuration Register */ APIC_SIPI = 0x3F, /* Self-IPI Register */ APIC_EAFR = 0x40, /* extended APIC Feature register */ APIC_EACR = 0x41, /* Extended APIC Control Register */ APIC_SEOI = 0x42, /* Specific End Of Interrupt Register */ APIC_EXT0LVTR = 0x50, /* Extended Interrupt 0 Local Vector Table */ APIC_EXT1LVTR = 0x51, /* Extended Interrupt 1 Local Vector Table */ APIC_EXT2LVTR = 0x52, /* Extended Interrupt 2 Local Vector Table */ APIC_EXT3LVTR = 0x53 /* Extended Interrupt 3 Local Vector Table */ } APIC_REGISTER, *PAPIC_REGISTER; /* APIC Timer Divide enumeration list */ typedef enum _APIC_TIMER_DIVISOR { TIMER_DivideBy2 = 0, TIMER_DivideBy4 = 1, TIMER_DivideBy8 = 2, TIMER_DivideBy16 = 3, TIMER_DivideBy32 = 8, TIMER_DivideBy64 = 9, TIMER_DivideBy128 = 10, TIMER_DivideBy1 = 11, } APIC_TIMER_DIVISOR, *PAPIC_TIMER_DIVISOR; /* I8259 PIC interrupt mode enumeration list */ typedef enum _PIC_I8259_ICW1_INTERRUPT_MODE { EdgeTriggered, LevelTriggered } PIC_I8259_ICW1_INTERRUPT_MODE, *PPIC_I8259_ICW1_INTERRUPT_MODE; /* I8259 PIC interval enumeration list */ typedef enum _PIC_I8259_ICW1_INTERVAL { Interval8, Interval4 } PIC_I8259_ICW1_INTERVAL, *PPIC_I8259_ICW1_INTERVAL; /* I8259 PIC operating mode enumeration list */ typedef enum _PIC_I8259_ICW1_OPERATING_MODE { Cascade, Single } PIC_I8259_ICW1_OPERATING_MODE, *PPIC_I8259_ICW1_OPERATING_MODE; /* I8259 PIC buffered mode enumeration list */ typedef enum _PIC_I8259_ICW4_BUFFERED_MODE { NonBuffered, NonBuffered2, BufferedSlave, BufferedMaster } PIC_I8259_ICW4_BUFFERED_MODE, *PPIC_I8259_ICW4_BUFFERED_MODE; /* I8259 PIC End Of Interrupt (EOI) mode enumeration list */ typedef enum _PIC_I8259_ICW4_EOI_MODE { NormalEoi, AutomaticEoi } PIC_I8259_ICW4_EOI_MODE, *PPIC_I8259_ICW4_EOI_MODE; /* I8259 PIC system mode enumeration list */ typedef enum _PIC_I8259_ICW4_SYSTEM_MODE { Mcs8085Mode, New8086Mode } PIC_I8259_ICW4_SYSTEM_MODE, *PPIC_I8259_ICW4_SYSTEM_MODE; /* Supported hardware timer backends */ typedef enum _TIMER_TYPE { TimerNone, TimerAcpiPm, TimerHpet, TimerLapic, TimerPit, TimerTsc } TIMER_TYPE, *PTIMER_TYPE; /* APIC Base Register */ typedef union _APIC_BASE_REGISTER { ULONGLONG LongLong; struct { ULONGLONG Reserved1:8; ULONGLONG BootStrapProcessor:1; ULONGLONG Reserved2:1; ULONGLONG ExtendedMode:1; ULONGLONG Enable:1; ULONGLONG BaseAddress:40; ULONGLONG Reserved3:12; }; } APIC_BASE_REGISTER, *PAPIC_BASE_REGISTER; /* APIC Command Register */ typedef union _APIC_COMMAND_REGISTER { ULONGLONG LongLong; struct { ULONG Long0; ULONG Long1; }; struct { ULONGLONG Vector:8; ULONGLONG DeliveryMode:3; ULONGLONG DestinationMode:1; ULONGLONG DeliveryStatus:1; ULONGLONG ReservedMBZ:1; ULONGLONG Level:1; ULONGLONG TriggerMode:1; ULONGLONG RemoteReadStatus:2; ULONGLONG DestinationShortHand:2; ULONGLONG Reserved2MBZ:36; ULONGLONG Destination:8; }; } APIC_COMMAND_REGISTER, *PAPIC_COMMAND_REGISTER; /* APIC Local Vector Table (LVT) Register */ typedef union _APIC_LVT_REGISTER { ULONG Long; struct { ULONG Vector:8; ULONG DeliveryMode:3; ULONG Reserved1:1; ULONG DeliveryStatus:1; ULONG Reserved2:1; ULONG RemoteIRR:1; ULONG TriggerMode:1; ULONG Mask:1; ULONG TimerMode:1; ULONG Reserved3:13; }; } APIC_LVT_REGISTER, *PAPIC_LVT_REGISTER; /* APIC Spurious Register */ typedef union _APIC_SPURIOUS_REGISTER { ULONG Long; struct { ULONG Vector:8; ULONG SoftwareEnable:1; ULONG CoreChecking:1; ULONG Reserved:22; }; } APIC_SPURIOUS_REGISTER, *PAPIC_SPURIOUS_REGISTER; /* I/O APIC Controller information */ typedef struct _IOAPIC_DATA { ULONG GsiBase; ULONG Identifier; ULONG LineCount; PHYSICAL_ADDRESS PhysicalAddress; ULONG_PTR VirtualAddress; } IOAPIC_DATA, *PIOAPIC_DATA; /* I/O APIC Redirection Register */ typedef union _IOAPIC_REDIRECTION_REGISTER { ULONGLONG LongLong; struct { UINT Base; UINT Extended; }; struct { ULONGLONG Vector:8; ULONGLONG DeliveryMode:3; ULONGLONG DestinationMode:1; ULONGLONG DeliveryStatus:1; ULONGLONG PinPolarity:1; ULONGLONG RemoteIRR:1; ULONGLONG TriggerMode:1; ULONGLONG Mask:1; ULONGLONG Reserved:39; ULONGLONG Destination:8; }; } IOAPIC_REDIRECTION_REGISTER, *PIOAPIC_REDIRECTION_REGISTER; /* I8259 PIC register structure */ typedef union _PIC_I8259_ICW1 { struct { UCHAR NeedIcw4:1; UCHAR OperatingMode:1; UCHAR Interval:1; UCHAR InterruptMode:1; UCHAR Init:1; UCHAR InterruptVectorAddress:3; }; UCHAR Bits; } PIC_I8259_ICW1, *PPIC_I8259_ICW1; /* I8259 PIC register structure */ typedef union _PIC_I8259_ICW2 { struct { UCHAR Sbz:3; UCHAR InterruptVector:5; }; UCHAR Bits; } PIC_I8259_ICW2, *PPIC_I8259_ICW2; /* I8259 PIC register structure */ typedef union _PIC_I8259_ICW3 { union { struct { UCHAR SlaveIrq0:1; UCHAR SlaveIrq1:1; UCHAR SlaveIrq2:1; UCHAR SlaveIrq3:1; UCHAR SlaveIrq4:1; UCHAR SlaveIrq5:1; UCHAR SlaveIrq6:1; UCHAR SlaveIrq7:1; }; struct { UCHAR SlaveId:3; UCHAR Reserved:5; }; }; UCHAR Bits; } PIC_I8259_ICW3, *PPIC_I8259_ICW3; /* I8259 PIC register structure */ typedef union _PIC_I8259_ICW4 { struct { UCHAR SystemMode:1; UCHAR EoiMode:1; UCHAR BufferedMode:2; UCHAR SpecialFullyNestedMode:1; UCHAR Reserved:3; }; UCHAR Bits; } PIC_I8259_ICW4, *PPIC_I8259_ICW4; /* HPET Registers structure definition */ typedef struct _HPET_REGISTERS { VOLATILE ULONGLONG GeneralCapabilities; VOLATILE ULONGLONG Reserved0; VOLATILE ULONGLONG GeneralConfiguration; VOLATILE ULONGLONG Reserved1; VOLATILE ULONGLONG GeneralInterruptStatus; VOLATILE ULONGLONG Reserved2; VOLATILE ULONGLONG Reserved3[2][12]; VOLATILE ULONGLONG MainCounterValue; VOLATILE ULONGLONG Reserved4; struct { VOLATILE ULONGLONG Configuration; VOLATILE ULONGLONG Comparator; VOLATILE ULONGLONG FsbInterruptRoute; VOLATILE ULONGLONG Reserved; } Timers[]; } HPET_REGISTERS, *PHPET_REGISTERS; /* Hardware timer capabilities and CPU clock features */ typedef struct _TIMER_CAPABILITIES { BOOLEAN Arat; BOOLEAN Art; BOOLEAN InvariantTsc; BOOLEAN RDTSCP; ULONG TimerFrequency; BOOLEAN TscDeadline; ULONG TscDenominator; ULONG TscNumerator; } TIMER_CAPABILITIES, *PTIMER_CAPABILITIES; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_I686_HLTYPES_H */ ================================================ FILE: sdk/xtdk/i686/ketypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/i686/ketypes.h * DESCRIPTION: Kernel services related structures definitions specific to i686 architecture * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_I686_KETYPES_H #define __XTDK_I686_KETYPES_H #include #include #include #include #include ARCH_HEADER(xtstruct.h) #include ARCH_HEADER(artypes.h) /* Selector masks */ #define MODE_MASK 0x0001 #define RPL_MASK 0x0003 /* GDT selector names */ #define KGDT_NULL 0x0000 #define KGDT_R0_CODE 0x0008 #define KGDT_R0_DATA 0x0010 #define KGDT_R3_CODE 0x0018 #define KGDT_R3_DATA 0x0020 #define KGDT_SYS_TSS 0x0028 #define KGDT_R0_PB 0x0030 #define KGDT_R3_TEB 0x0038 #define KGDT_VDM_TILE 0x0040 #define KGDT_R0_LDT 0x0048 #define KGDT_DF_TSS 0x0050 #define KGDT_NMI_TSS 0x0058 #define KGDT_VDBS 0x0068 #define KGDT_ALIAS 0x0070 /* GDT descriptor privilege levels */ #define KGDT_DPL_SYSTEM 0 #define KGDT_DPL_USER 3 /* GDT descriptor properties */ #define KGDT_DESCRIPTOR_ACCESSED 0x01 #define KGDT_DESCRIPTOR_READ_WRITE 0x02 #define KGDT_DESCRIPTOR_EXECUTE_READ 0x02 #define KGDT_DESCRIPTOR_EXPAND_DOWN 0x04 #define KGDT_DESCRIPTOR_CONFORMING 0x04 #define KGDT_DESCRIPTOR_CODE 0x08 /* GDT descriptor type codes */ #define KGDT_TYPE_NONE 0x00 #define KGDT_TYPE_CODE (0x10 | KGDT_DESCRIPTOR_CODE | KGDT_DESCRIPTOR_EXECUTE_READ) #define KGDT_TYPE_DATA (0x10 | KGDT_DESCRIPTOR_READ_WRITE) /* IDT access levels */ #define KIDT_ACCESS_RING0 0x00 #define KIDT_ACCESS_RING3 0x60 /* TSS Offsets */ #define KTSS_ESP0 0x04 #define KTSS_CR3 0x1C #define KTSS_EIP 0x20 #define KTSS_EFLAGS 0x24 #define KTSS_EAX 0x28 #define KTSS_ECX 0x2C #define KTSS_EDX 0x30 #define KTSS_EBX 0x34 #define KTSS_ESP 0x38 #define KTSS_EBP 0x3C #define KTSS_ESI 0x40 #define KTSS_EDI 0x44 #define KTSS_ES 0x48 #define KTSS_CS 0x4C #define KTSS_SS 0x50 #define KTSS_DS 0x54 #define KTSS_FS 0x58 #define KTSS_GS 0x5C #define KTSS_LDT 0x60 #define KTSS_IOMAPBASE 0x66 #define KTSS_IO_MAPS 0x68 /* I686 Segment Types */ #define I686_LDT 0x2 #define I686_TASK_GATE 0x5 #define I686_TSS 0x9 #define I686_ACTIVE_TSS 0xB #define I686_CALL_GATE 0xC #define I686_INTERRUPT_GATE 0xE #define I686_TRAP_GATE 0xF /* Kernel CPU Standard Features */ #define KCF_VME (1ULL << 0) /* Virtual 8086 Mode Enhancements */ #define KCF_LARGE_PAGE (1ULL << 1) /* Page Size Extensions */ #define KCF_RDTSC (1ULL << 2) /* Time Stamp Counter */ #define KCF_PAE (1ULL << 3) /* Physical Address Extension */ #define KCF_MCE (1ULL << 4) /* Machine Check Exception */ #define KCF_CMPXCHG8B (1ULL << 5) /* CMPXCHG8B Instruction */ #define KCF_APIC (1ULL << 6) /* APIC On-Chip */ #define KCF_FAST_SYSCALL (1ULL << 7) /* SYSENTER/SYSEXIT Instructions */ #define KCF_MTRR (1ULL << 8) /* Memory Type Range Registers */ #define KCF_GLOBAL_PAGE (1ULL << 9) /* Page Global Enable */ #define KCF_MCA (1ULL << 10) /* Machine Check Architecture */ #define KCF_CMOV (1ULL << 11) /* Conditional Move Instructions */ #define KCF_PAT (1ULL << 12) /* Page Attribute Table */ #define KCF_PSE36 (1ULL << 13) /* 36-bit Page Size Extension */ #define KCF_CLFLUSH (1ULL << 14) /* CLFLUSH Instruction */ #define KCF_FXSR (1ULL << 15) /* FXSAVE/FXRSTOR Instructions */ #define KCF_ACPI (1ULL << 16) /* Thermal Monitor and Software Controlled Clock */ #define KCF_MMX (1ULL << 17) /* MMX Technology */ #define KCF_SSE (1ULL << 18) /* Streaming SIMD Extensions */ #define KCF_SSE2 (1ULL << 19) /* Streaming SIMD Extensions 2 */ #define KCF_SMT (1ULL << 20) /* Hyper-Threading Technology */ #define KCF_SSE3 (1ULL << 21) /* Streaming SIMD Extensions 3 */ #define KCF_VMX (1ULL << 22) /* Intel Virtual Machine Extensions */ #define KCF_SSSE3 (1ULL << 23) /* Supplemental SSE3 Instructions */ #define KCF_SSE41 (1ULL << 24) /* SSE4.1 Instructions */ #define KCF_SSE42 (1ULL << 25) /* SSE4.2 Instructions */ #define KCF_X2APIC (1ULL << 26) /* x2APIC Support */ #define KCF_POPCNT (1ULL << 27) /* POPCNT Instruction */ #define KCF_TSC_DEADLINE (1ULL << 28) /* TSC Deadline Timer */ #define KCF_AES (1ULL << 29) /* AES-NI Instruction Set */ #define KCF_XSAVE (1ULL << 30) /* XSAVE/XRSTOR Instructions */ #define KCF_AVX (1ULL << 31) /* Advanced Vector Extensions */ #define KCF_RDRAND (1ULL << 32) /* RDRAND Instruction */ #define KCF_FSGSBASE (1ULL << 33) /* RDFSBASE/WRFSBASE Instructions */ #define KCF_AVX2 (1ULL << 34) /* AVX2 Instructions */ #define KCF_SMEP (1ULL << 35) /* Supervisor Mode Execution Prevention */ #define KCF_RDSEED (1ULL << 36) /* RDSEED Instruction */ #define KCF_SMAP (1ULL << 37) /* Supervisor Mode Access Prevention */ #define KCF_SHA (1ULL << 38) /* SHA Extensions */ #define KCF_LA57 (1ULL << 39) /* 57-bit Linear Addresses */ #define KCF_ARAT (1ULL << 40) /* Always Running APIC Timer */ /* Kernel CPU Extended Features */ #define KCF_SVM (1ULL << 0) /* AMD Secure Virtual Machine */ #define KCF_SSE4A (1ULL << 1) /* SSE4A Instructions */ #define KCF_FMA4 (1ULL << 2) /* FMA4 Instructions */ #define KCF_TOPOEXT (1ULL << 3) /* AMD Topology Extensions */ #define KCF_SYSCALL (1ULL << 4) /* SYSCALL/SYSRET Instructions */ #define KCF_NX_BIT (1ULL << 5) /* No-Execute Page Protection */ #define KCF_RDTSCP (1ULL << 6) /* RDTSCP Instruction */ #define KCF_64BIT (1ULL << 7) /* Long Mode Support */ #define KCF_3DNOW_EXT (1ULL << 8) /* 3DNow! Extensions */ #define KCF_3DNOW (1ULL << 9) /* 3DNow! Instructions */ #define KCF_INVARIANT_TSC (1ULL << 10) /* Invariant Time Stamp Counter */ /* Context control flags */ #define CONTEXT_ARCHITECTURE 0x00010000 #define CONTEXT_CONTROL (CONTEXT_ARCHITECTURE | 0x01) #define CONTEXT_INTEGER (CONTEXT_ARCHITECTURE | 0x02) #define CONTEXT_SEGMENTS (CONTEXT_ARCHITECTURE | 0x04) #define CONTEXT_FLOATING_POINT (CONTEXT_ARCHITECTURE | 0x08) #define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARCHITECTURE | 0x10) #define CONTEXT_EXTENDED_REGISTERS (CONTEXT_ARCHITECTURE | 0x20) /* Interrupt request levels definitions */ #define PASSIVE_LEVEL 0 #define LOW_LEVEL 0 #define APC_LEVEL 1 #define DISPATCH_LEVEL 2 #define CMCI_LEVEL 5 #define DEVICE1_LEVEL 6 #define DEVICE2_LEVEL 7 #define DEVICE3_LEVEL 8 #define DEVICE4_LEVEL 9 #define DEVICE5_LEVEL 10 #define DEVICE6_LEVEL 11 #define DEVICE7_LEVEL 12 #define PROFILE_LEVEL 27 #define SYNC_LEVEL 27 #define CLOCK_LEVEL 28 #define IPI_LEVEL 29 #define POWER_LEVEL 30 #define HIGH_LEVEL 31 /* IOPM Definitions */ #define IOPM_COUNT 1 #define IOPM_SIZE 8192 #define IOPM_FULL_SIZE 8196 #define IOPM_ACCESS_MAP_NONE 0 #define IOPM_DIRECTION_MAP_SIZE 32 /* Static Kernel-Mode address start */ #define KSEG0_BASE 0x80000000 /* XTOS Kernel stack size */ #define KERNEL_STACK_SIZE 0x4000 #define KERNEL_STACKS 3 /* XTOS Kernel stack guard pages */ #define KERNEL_STACK_GUARD_PAGES 1 /* Processor structures size */ #define KPROCESSOR_STRUCTURES_SIZE ((KERNEL_STACKS * KERNEL_STACK_SIZE) + (GDT_ENTRIES * sizeof(KGDTENTRY)) + \ sizeof(KTSS) + sizeof(KPROCESSOR_BLOCK) + MM_PAGE_SIZE) /* Kernel frames */ #define KTRAP_FRAME_ALIGN 0x08 #define KTRAP_FRAME_SIZE sizeof(KTRAP_FRAME) #define NPX_FRAME_SIZE 0x210 /* Number of supported extensions */ #define MAXIMUM_SUPPORTED_EXTENSION 512 /* Return address size pushed by 'call' instruction */ #define KRETURN_ADDRESS_SIZE 0x4 /* Size of 387 registers */ #define SIZE_OF_80387_REGISTERS 80 #define SIZE_OF_FX_REGISTERS 128 /* NPX state definitions */ #define NPX_STATE_LOADED 0x0 #define NPX_STATE_UNLOADED 0xA /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Floating point state storing structure */ typedef struct _FN_SAVE_FORMAT { ULONG ControlWord; ULONG StatusWord; ULONG TagWord; ULONG ErrorOffset; ULONG ErrorSelector; ULONG DataOffset; ULONG DataSelector; UCHAR RegisterArea[SIZE_OF_80387_REGISTERS]; ULONG Cr0NpxState; } FN_SAVE_FORMAT, *PFN_SAVE_FORMAT; /* Data for FXSAVE/FXRSTOR instructions structure definition */ typedef struct _FX_SAVE_FORMAT { USHORT ControlWord; USHORT StatusWord; USHORT TagWord; USHORT ErrorOpcode; ULONG ErrorOffset; ULONG ErrorSelector; ULONG DataOffset; ULONG DataSelector; ULONG MxCsr; ULONG MxCsrMask; UCHAR RegisterArea[SIZE_OF_FX_REGISTERS]; UCHAR Reserved3[SIZE_OF_FX_REGISTERS]; UCHAR Reserved4[224]; UCHAR Align16Byte[8]; } FX_SAVE_FORMAT, *PFX_SAVE_FORMAT; /* Floating save area structure definition */ typedef struct _FX_SAVE_AREA { union { FN_SAVE_FORMAT FnArea; FX_SAVE_FORMAT FxArea; }; ULONG NpxSavedCpu; ULONG Cr0NpxState; } FX_SAVE_AREA, *PFX_SAVE_AREA; /* Context frame structure definition */ typedef struct _CONTEXT { ULONG ContextFlags; ULONG Dr0; ULONG Dr1; ULONG Dr2; ULONG Dr3; ULONG Dr6; ULONG Dr7; FN_SAVE_FORMAT FloatSave; ULONG SegGs; ULONG SegFs; ULONG SegEs; ULONG SegDs; ULONG Edi; ULONG Esi; ULONG Ebx; ULONG Edx; ULONG Ecx; ULONG Eax; ULONG Ebp; ULONG Eip; ULONG SegCs; ULONG EFlags; ULONG Esp; ULONG SegSs; UCHAR ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION]; } CONTEXT, *PCONTEXT; /* Pseudo descriptor structure definition */ typedef struct _KDESCRIPTOR { USHORT Pad; USHORT Limit; PVOID Base; } KDESCRIPTOR, *PKDESCRIPTOR; /* Global Descriptor Table (GDT) entry structure definition */ typedef struct _KGDTENTRY { USHORT LimitLow; USHORT BaseLow; union { struct { UCHAR BaseMiddle; UCHAR Flags1; UCHAR Flags2; UCHAR BaseHigh; } Bytes; struct { ULONG BaseMiddle:8; ULONG Type:5; ULONG Dpl:2; ULONG Present:1; ULONG LimitHigh:4; ULONG System:1; ULONG Reserved0:1; ULONG DefaultBig:1; ULONG Granularity:1; ULONG BaseHigh:8; } Bits; }; } KGDTENTRY, *PKGDTENTRY; /* Interrupt Descriptor Table (IDT) entry structure definition */ typedef struct _KIDTENTRY { USHORT Offset; USHORT Selector; union { struct { UCHAR Reserved; UCHAR Type:4; UCHAR Flag:1; UCHAR Dpl:2; UCHAR Present:1; }; USHORT Access; }; USHORT ExtendedOffset; } KIDTENTRY, *PKIDTENTRY; /* Interrupt direction access map structure definition */ typedef struct _KIIO_ACCESS_MAP { UCHAR DirectionMap[IOPM_DIRECTION_MAP_SIZE]; UCHAR IoMap[IOPM_FULL_SIZE]; } KIIO_ACCESS_MAP, *PKIIO_ACCESS_MAP; /* Task State Segment (TSS) structure definition */ typedef struct _KTSS { USHORT Backlink; USHORT Reserved0; ULONG Esp0; USHORT Ss0; USHORT Reserved1; ULONG NotUsed1[4]; ULONG CR3; ULONG Eip; ULONG EFlags; ULONG Eax; ULONG Ecx; ULONG Edx; ULONG Ebx; ULONG Esp; ULONG Ebp; ULONG Esi; ULONG Edi; USHORT Es; USHORT Reserved2; USHORT Cs; USHORT Reserved3; USHORT Ss; USHORT Reserved4; USHORT Ds; USHORT Reserved5; USHORT Fs; USHORT Reserved6; USHORT Gs; USHORT Reserved7; USHORT LDT; USHORT Reserved8; USHORT Flags; USHORT IoMapBase; KIIO_ACCESS_MAP IoMaps[IOPM_COUNT]; UCHAR IntDirectionMap[IOPM_DIRECTION_MAP_SIZE]; } KTSS, *PKTSS; /* Exception frame definition (not available on i686) */ typedef struct _KEXCEPTION_FRAME { ULONG Ebp; ULONG Ebx; ULONG Edi; ULONG Esi; ULONG Return; } KEXCEPTION_FRAME, *PKEXCEPTION_FRAME; /* Thread start frame definition */ typedef struct _KSTART_FRAME { PKSYSTEM_ROUTINE SystemRoutine; PKSTART_ROUTINE StartRoutine; PVOID StartContext; BOOLEAN UserMode; } KSTART_FRAME, *PKSTART_FRAME; /* Switch frame definition */ typedef struct _KSWITCH_FRAME { PVOID ExceptionList; BOOLEAN ApcBypassDisabled; PVOID Return; } KSWITCH_FRAME, *PKSWITCH_FRAME; /* Trap frame definition */ typedef struct _KTRAP_FRAME { ULONG PreviousMode; ULONG Cr2; ULONG Cr3; ULONG Dr0; ULONG Dr1; ULONG Dr2; ULONG Dr3; ULONG Dr6; ULONG Dr7; USHORT SegDs; USHORT SegEs; USHORT SegFs; USHORT SegGs; ULONG Eax; ULONG Ebx; ULONG Ecx; ULONG Edx; ULONG Esi; ULONG Edi; ULONG Ebp; ULONG Vector; ULONG ErrorCode; ULONG Eip; ULONG SegCs; ULONG Flags; ULONG Esp; ULONG SegSs; } KTRAP_FRAME, *PKTRAP_FRAME; /* Thread initialization frame definition */ typedef struct _KTHREAD_INIT_FRAME { KSWITCH_FRAME SwitchFrame; KSTART_FRAME StartFrame; KTRAP_FRAME TrapFrame; FX_SAVE_AREA NpxFrame; } KTHREAD_INIT_FRAME, *PKTHREAD_INIT_FRAME; /* Special kernel registers structure definition */ typedef struct _KSPECIAL_REGISTERS { ULONG Cr0; ULONG Cr2; ULONG Cr3; ULONG Cr4; ULONG KernelDr0; ULONG KernelDr1; ULONG KernelDr2; ULONG KernelDr3; ULONG KernelDr6; ULONG KernelDr7; KDESCRIPTOR Gdtr; KDESCRIPTOR Idtr; USHORT Tr; USHORT Ldtr; ULONG Reserved[6]; } KSPECIAL_REGISTERS, *PKSPECIAL_REGISTERS; /* Processor start block structure definition */ typedef struct _PROCESSOR_START_BLOCK { ULONG_PTR Cr3; ULONG_PTR Cr4; PVOID EntryPoint; PVOID ProcessorStructures; PVOID Stack; BOOLEAN Started; } PROCESSOR_START_BLOCK, *PPROCESSOR_START_BLOCK; /* Processor state frame structure definition */ typedef struct _KPROCESSOR_STATE { CONTEXT ContextFrame; KSPECIAL_REGISTERS SpecialRegisters; } KPROCESSOR_STATE, *PKPROCESSOR_STATE; /* Processor Control Block (PRCB) structure definition */ typedef struct _KPROCESSOR_CONTROL_BLOCK { PKTHREAD CurrentThread; PKTHREAD IdleThread; PKTHREAD NextThread; UCHAR CpuNumber; ULONG_PTR SetMember; CPU_IDENTIFICATION CpuId; KPROCESSOR_STATE ProcessorState; KSPIN_LOCK_QUEUE LockQueue[MaximumLock]; ULONG_PTR MultiThreadProcessorSet; KDPC_DATA DpcData[2]; PVOID DpcStack; VOLATILE BOOLEAN DpcRoutineActive; VOLATILE ULONG_PTR TimerRequest; SINGLE_LIST_ENTRY DeferredReadyListHead; PROCESSOR_POWER_STATE PowerState; ULONG ProfilingCountdown; } KPROCESSOR_CONTROL_BLOCK, *PKPROCESSOR_CONTROL_BLOCK; /* Processor Block structure definition */ typedef struct _KPROCESSOR_BLOCK { union { THREAD_INFORMATION_BLOCK ThreadInformationBlock; struct { PKGDTENTRY GdtBase; PKTSS TssBase; PKPROCESSOR_BLOCK Self; PKPROCESSOR_CONTROL_BLOCK CurrentPrcb; }; }; PKIDTENTRY IdtBase; KRUNLEVEL RunLevel; KPROCESSOR_CONTROL_BLOCK Prcb; ULONG Irr; ULONG IrrActive; ULONG Idr; ULONG ContextSwitches; KAFFINITY SetMember; ULONG StallScaleFactor; UCHAR CpuNumber; ULONG HardwareId; VOLATILE BOOLEAN Started; PINTERRUPT_HANDLER InterruptDispatchTable[256]; } KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK; /* Thread Environment Block (TEB) structure definition */ typedef struct _THREAD_ENVIRONMENT_BLOCK { THREAD_INFORMATION_BLOCK InformationBlock; } THREAD_ENVIRONMENT_BLOCK, *PTHREAD_ENVIRONMENT_BLOCK; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_I686_KETYPES_H */ ================================================ FILE: sdk/xtdk/i686/mmtypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/i686/mmtypes.h * DESCRIPTION: Memory management data structures for i686 architecture * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_I686_MMTYPES_H #define __XTDK_I686_MMTYPES_H #include #include /* Pages related definitions */ #define MM_PAGE_MASK (MM_PAGE_SIZE - 1) #define MM_PAGE_SHIFT 12 #define MM_PAGE_SIZE 4096 /* Page directory and page base addresses */ #define MM_PTE_BASE 0xC0000000 #define MM_PDE_BASE 0xC0600000 /* PTE shift values */ #define MM_PTE_SHIFT 3 #define MM_PTI_SHIFT 12 #define MM_PDI_SHIFT 21 #define MM_PPI_SHIFT 30 /* Page directory and page base legacy address */ #define MM_PDE_LEGACY_BASE 0xC0300000 /* PTE legacy shift values */ #define MM_PTE_LEGACY_SHIFT 2 #define MM_PDI_LEGACY_SHIFT 22 /* PTE state flags */ #define MM_PTE_VALID 0x00000001 #define MM_PTE_ACCESSED 0x00000020 #define MM_PTE_DIRTY 0x00000040 /* PTE scope flags */ #define MM_PTE_LARGE_PAGE 0x00000080 #define MM_PTE_GLOBAL 0x00000100 /* PTE access flags */ #define MM_PTE_NOACCESS 0x00000000 #define MM_PTE_READONLY 0x00000000 #define MM_PTE_EXECUTE 0x00000000 #define MM_PTE_EXECUTE_READ 0x00000000 #define MM_PTE_READWRITE 0x00000002 #define MM_PTE_WRITECOPY 0x00000200 #define MM_PTE_EXECUTE_READWRITE 0x00000002 #define MM_PTE_EXECUTE_WRITECOPY 0x00000200 /* PTE protection flags */ #define MM_PTE_NOEXECUTE 0x00000000 #define MM_PTE_GUARDED 0x00000018 #define MM_PTE_PROTECT 0x00000612 /* PTE cache flags */ #define MM_PTE_CACHE_ENABLE 0x00000000 #define MM_PTE_CACHE_DISABLE 0x00000010 #define MM_PTE_CACHE_WRITECOMBINED 0x00000010 #define MM_PTE_CACHE_WRITETHROUGH 0x00000008 /* PTE software flags */ #define MM_PTE_COPY_ON_WRITE 0x00000200 #define MM_PTE_PROTOTYPE 0x00000400 #define MM_PTE_TRANSITION 0x00000800 /* PTE frame bits */ #define MM_PTE_FRAME_BITS 25 /* PTE protection bits */ #define MM_PTE_PROTECTION_BITS 5 /* Base address of the system page table */ #define MM_SYSTEM_PTE_BASE NULLPTR /* Minimum number of physical pages needed by the system */ #define MM_MINIMUM_PHYSICAL_PAGES 1100 /* Number of system PTEs */ #define MM_MINIMUM_NUMBER_SYSTEM_PTES 7000 #define MM_DEFAULT_NUMBER_SYSTEM_PTES 11000 #define MM_MAXIMUM_NUMBER_SYSTEM_PTES 22000 /* Default number of secondary colors */ #define MM_DEFAULT_SECONDARY_COLORS 64 /* Number of HAL allocation descriptors */ #define MM_HARDWARE_ALLOCATION_DESCRIPTORS 64 /* Kernel HAL heap initial start address */ #define MM_HARDWARE_HEAP_START_ADDRESS ((PVOID)(((ULONG_PTR)MM_HARDWARE_VA_START) + 1024 * 1024)) /* HAL memory pool virtual address start */ #define MM_HARDWARE_VA_START 0xFFC00000 /* Kernel shared data address */ #define MM_KERNEL_SHARED_DATA_ADDRESS 0xFFDF0000 /* Maximum physical address used by HAL allocations */ #define MM_MAXIMUM_PHYSICAL_ADDRESS 0xFFFFFFFF /* Highest system address */ #define MM_HIGHEST_SYSTEM_ADDRESS 0xFFFFFFFF /* Trampoline code address */ #define MM_TRAMPOLINE_ADDRESS 0x80000 /* Pool block size */ #define MM_POOL_BLOCK_SIZE 8 /* Number of pool lists per page */ #define MM_POOL_LISTS_PER_PAGE (MM_PAGE_SIZE / MM_POOL_BLOCK_SIZE) /* Number of pool tracking tables */ #define MM_POOL_TRACKING_TABLES 32 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Page size enumeration list */ typedef enum _PAGE_SIZE { Size4K, Size2M, Size4M } PAGE_SIZE, *PPAGE_SIZE; /* Legacy Page Table entry structure definition (PML2) */ typedef struct _HARDWARE_LEGACY_PTE { ULONG Valid:1; ULONG Writable:1; ULONG Owner:1; ULONG WriteThrough:1; ULONG CacheDisable:1; ULONG Accessed:1; ULONG Dirty:1; ULONG LargePage:1; ULONG Global:1; ULONG CopyOnWrite:1; ULONG Prototype:1; ULONG Reserved0:1; ULONG PageFrameNumber:20; } HARDWARE_LEGACY_PTE, *PHARDWARE_LEGACY_PTE; /* Page Table entry structure definition (PML3) */ typedef struct _HARDWARE_MODERN_PTE { ULONGLONG Valid:1; ULONGLONG Writable:1; ULONGLONG Owner:1; ULONGLONG WriteThrough:1; ULONGLONG CacheDisable:1; ULONGLONG Accessed:1; ULONGLONG Dirty:1; ULONGLONG LargePage:1; ULONGLONG Global:1; ULONGLONG CopyOnWrite:1; ULONGLONG Prototype:1; ULONGLONG Reserved0:1; ULONGLONG PageFrameNumber:26; ULONGLONG Reserved1:14; ULONGLONG SoftwareWsIndex:11; ULONGLONG NoExecute:1; } HARDWARE_MODERN_PTE, *PHARDWARE_MODERN_PTE; /* Generic Page Table entry union to abstract PML2 and PML3 formats */ typedef union _HARDWARE_PTE { HARDWARE_LEGACY_PTE Pml2; HARDWARE_MODERN_PTE Pml3; } HARDWARE_PTE, *PHARDWARE_PTE; /* Page map information structure definition */ typedef struct _MMPAGEMAP_INFO { BOOLEAN Xpa; ULONG PteBase; ULONG PdeBase; ULONG PdiShift; ULONG PteShift; } MMPAGEMAP_INFO, *PMMPAGEMAP_INFO; /* Legacy Page Table Entry hardware structure definition (PML2) */ typedef struct _MMPML2_PTE_HARDWARE { ULONG Valid:1; ULONG Writable:1; ULONG Owner:1; ULONG WriteThrough:1; ULONG CacheDisable:1; ULONG Accessed:1; ULONG Dirty:1; ULONG LargePage:1; ULONG Global:1; ULONG CopyOnWrite:1; ULONG Prototype:1; ULONG Write:1; ULONG PageFrameNumber:20; } MMPML2_PTE_HARDWARE, *PMMPML2_PTE_HARDWARE; /* Legacy Page Table Entry list structure definition (PML2) */ typedef struct _MMPML2_PTE_LIST { ULONG Valid:1; ULONG OneEntry:1; ULONG Reserved0:8; ULONG Prototype:1; ULONG Reserved1:1; ULONG NextEntry:20; } MMPML2_PTE_LIST, *PMMPML2_PTE_LIST; /* Legacy Page Table Entry subsection structure definition (PML2) */ typedef struct _MMPML2_PTE_PROTOTYPE { ULONG Valid:1; ULONG ProtoAddressLow:7; ULONG ReadOnly:1; ULONG WhichPool:1; ULONG Prototype:1; ULONG ProtoAddressHigh:21; } MMPML2_PTE_PROTOTYPE, *PMMPML2_PTE_PROTOTYPE; /* Legacy Page Table Entry software structure definition (PML2) */ typedef struct _MMPML2_PTE_SOFTWARE { ULONG Valid:1; ULONG PageFileLow:4; ULONG Protection:5; ULONG Prototype:1; ULONG Transition:1; ULONG PageFileHigh:20; } MMPML2_PTE_SOFTWARE, *PMMPML2_PTE_SOFTWARE; /* Legacy Page Table Entry subsection structure definition (PML2) */ typedef struct _MMPML2_PTE_SUBSECTION { ULONG Valid:1; ULONG SubsectionAddressLow:4; ULONG Protection:5; ULONG Prototype:1; ULONG SubsectionAddressHigh:20; ULONG WhichPool:1; } MMPML2_PTE_SUBSECTION, *PMMPML2_PTE_SUBSECTION; /* Legacy Page Table Entry transition structure definition (PML2) */ typedef struct _MMPML2_PTE_TRANSITION { ULONG Valid:1; ULONG Write:1; ULONG Owner:1; ULONG WriteThrough:1; ULONG CacheDisable:1; ULONG Protection:5; ULONG Prototype:1; ULONG Transition:1; ULONG PageFrameNumber:20; } MMPML2_PTE_TRANSITION, *PMMPML2_PTE_TRANSITION; /* Legacy Page Table Entry union definition (PML2) */ typedef union _MMPML2_PTE { ULONG Long; HARDWARE_LEGACY_PTE Flush; MMPML2_PTE_HARDWARE Hardware; MMPML2_PTE_PROTOTYPE Prototype; MMPML2_PTE_SOFTWARE Software; MMPML2_PTE_TRANSITION Transition; MMPML2_PTE_SUBSECTION Subsection; MMPML2_PTE_LIST List; } MMPML2_PTE, *PMMPML2_PTE; /* Page Table Entry hardware structure definition (PML3) */ typedef struct _MMPML3_PTE_HARDWARE { ULONGLONG Valid:1; ULONGLONG Writable:1; ULONGLONG Owner:1; ULONGLONG WriteThrough:1; ULONGLONG CacheDisable:1; ULONGLONG Accessed:1; ULONGLONG Dirty:1; ULONGLONG LargePage:1; ULONGLONG Global:1; ULONGLONG CopyOnWrite:1; ULONGLONG Prototype:1; ULONGLONG Write:1; ULONGLONG PageFrameNumber:26; ULONGLONG Reserved0:25; ULONGLONG NoExecute:1; } MMPML3_PTE_HARDWARE, *PMMPML3_PTE_HARDWARE; /* Page Table Entry list structure definition (PML3) */ typedef struct _MMPML3_PTE_LIST { ULONGLONG Valid:1; ULONGLONG OneEntry:1; ULONGLONG Reserved0:8; ULONGLONG Prototype:1; ULONGLONG Reserved1:21; ULONGLONG NextEntry:32; } MMPML3_PTE_LIST, *PMMPML3_PTE_LIST; /* Page Table Entry subsection structure definition (PML3) */ typedef struct _MMPML3_PTE_PROTOTYPE { ULONGLONG Valid:1; ULONGLONG Reserved0:7; ULONGLONG ReadOnly:1; ULONGLONG Reserved1:1; ULONGLONG Prototype:1; ULONGLONG Protection:5; ULONGLONG Reserved2:16; ULONGLONG ProtoAddress:32; } MMPML3_PTE_PROTOTYPE, *PMMPML3_PTE_PROTOTYPE; /* Page Table Entry software structure definition (PML3) */ typedef struct _MMPML3_PTE_SOFTWARE { ULONGLONG Valid:1; ULONGLONG PageFileLow:4; ULONGLONG Protection:5; ULONGLONG Prototype:1; ULONGLONG Transition:1; ULONGLONG Reserved0:20; ULONGLONG PageFileHigh:32; } MMPML3_PTE_SOFTWARE, *PMMPML3_PTE_SOFTWARE; /* Page Table Entry subsection structure definition (PML3) */ typedef struct _MMPML3_PTE_SUBSECTION { ULONGLONG Valid:1; ULONGLONG Reserved0:4; ULONGLONG Protection:5; ULONGLONG Prototype:1; ULONGLONG Reserved1:21; ULONGLONG SubsectionAddress:32; } MMPML3_PTE_SUBSECTION, *PMMPML3_PTE_SUBSECTION; /* Page Table Entry transition structure definition (PML3) */ typedef struct _MMPML3_PTE_TRANSITION { ULONGLONG Valid:1; ULONGLONG Write:1; ULONGLONG Owner:1; ULONGLONG WriteThrough:1; ULONGLONG CacheDisable:1; ULONGLONG Protection:5; ULONGLONG Prototype:1; ULONGLONG Transition:1; ULONGLONG PageFrameNumber:26; ULONGLONG Unused:26; } MMPML3_PTE_TRANSITION, *PMMPML3_PTE_TRANSITION; /* Page Table Entry union definition (PML3) */ typedef union _MMPML3_PTE { ULONGLONG Long; HARDWARE_MODERN_PTE Flush; MMPML3_PTE_HARDWARE Hardware; MMPML3_PTE_PROTOTYPE Prototype; MMPML3_PTE_SOFTWARE Software; MMPML3_PTE_TRANSITION Transition; MMPML3_PTE_SUBSECTION Subsection; MMPML3_PTE_LIST List; } MMPML3_PTE, *PMMPML3_PTE; /* Generic Page Table Entry union to abstract PML2 and PML3 formats */ typedef union _MMPTE { MMPML2_PTE Pml2; MMPML3_PTE Pml3; } MMPTE, *PMMPTE; /* Page Frame Number structure definition */ typedef struct _MMPFN { union { PFN_NUMBER Flink; ULONG WsIndex; PKEVENT Event; XTSTATUS ReadStatus; SINGLE_LIST_ENTRY NextStackPfn; } u1; PMMPTE PteAddress; union { PFN_NUMBER Blink; ULONG_PTR ShareCount; } u2; union { MMPFNENTRY e1; struct { USHORT ShortFlags; USHORT ReferenceCount; } e2; } u3; ULONG UsedPageTableEntries; union { MMPTE OriginalPte; LONG AweReferenceCount; }; union { ULONG_PTR EntireFrame; struct { ULONG_PTR PteFrame:25; ULONG_PTR InPageError:1; ULONG_PTR VerifierAllocation:1; ULONG_PTR AweAllocation:1; ULONG_PTR Priority:3; ULONG_PTR MustBeCached:1; }; } u4; } MMPFN, *PMMPFN; /* Pool descriptor structure definition */ typedef struct _POOL_DESCRIPTOR { LIST_ENTRY ListHeads[MM_POOL_LISTS_PER_PAGE]; PVOID LockAddress; ULONG PoolIndex; LONG PendingFreeDepth; PVOID PendingFrees; MMPOOL_TYPE PoolType; ULONG RunningFrees; ULONG RunningAllocations; ULONG Threshold; ULONG TotalPages; ULONG TotalBigAllocations; SIZE_T TotalBytes; SIZE_T Reserved; } POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_I686_MMTYPES_H */ ================================================ FILE: sdk/xtdk/i686/xtstruct.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/i686/xtstruct.h * DESCRIPTION: XT structures forward references specific to i686 architecture * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_I686_XTSTRUCT_H #define __XTDK_I686_XTSTRUCT_H #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Architecture-specific enumeration lists forward references */ typedef enum _APIC_DEST_MODE APIC_DEST_MODE, *PAPIC_DEST_MODE; typedef enum _APIC_DM APIC_DM, *PAPIC_DM; typedef enum _APIC_DSH APIC_DSH, *PAPIC_DSH; typedef enum _APIC_MODE APIC_MODE, *PAPIC_MODE; typedef enum _APIC_REGISTER APIC_REGISTER, *PAPIC_REGISTER; typedef enum _APIC_TIMER_DIVISOR APIC_TIMER_DIVISOR, *PAPIC_TIMER_DIVISOR; typedef enum _CPU_VENDOR CPU_VENDOR, *PCPU_VENDOR; typedef enum _CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT, *PCPUID_FEATURES_ADVANCED_POWER_MANAGEMENT; typedef enum _CPUID_FEATURES_EXTENDED CPUID_FEATURES_EXTENDED, *PCPUID_FEATURES_EXTENDED; typedef enum _CPUID_FEATURES_POWER_MANAGEMENT CPUID_FEATURES_POWER_MANAGEMENT, *PCPUID_FEATURES_POWER_MANAGEMENT; typedef enum _CPUID_FEATURES_STANDARD1 CPUID_FEATURES_STANDARD1, *PCPUID_FEATURES_STANDARD1; typedef enum _CPUID_FEATURES_STANDARD7_LEAF0 CPUID_FEATURES_STANDARD7_LEAF0, *PCPUID_FEATURES_STANDARD7_LEAF0; typedef enum _CPUID_FEATURES_STANDARD7_LEAF1 CPUID_FEATURES_STANDARD7_LEAF1, *PCPUID_FEATURES_STANDARD7_LEAF1; typedef enum _CPUID_REQUESTS CPUID_REQUESTS, *PCPUID_REQUESTS; typedef enum _PAGE_SIZE PAGE_SIZE, *PPAGE_SIZE; typedef enum _PIC_I8259_ICW1_INTERRUPT_MODE PIC_I8259_ICW1_INTERRUPT_MODE, *PPIC_I8259_ICW1_INTERRUPT_MODE; typedef enum _PIC_I8259_ICW1_INTERVAL PIC_I8259_ICW1_INTERVAL, *PPIC_I8259_ICW1_INTERVAL; typedef enum _PIC_I8259_ICW1_OPERATING_MODE PIC_I8259_ICW1_OPERATING_MODE, *PPIC_I8259_ICW1_OPERATING_MODE; typedef enum _PIC_I8259_ICW4_BUFFERED_MODE PIC_I8259_ICW4_BUFFERED_MODE, *PPIC_I8259_ICW4_BUFFERED_MODE; typedef enum _PIC_I8259_ICW4_EOI_MODE PIC_I8259_ICW4_EOI_MODE, *PPIC_I8259_ICW4_EOI_MODE; typedef enum _PIC_I8259_ICW4_SYSTEM_MODE PIC_I8259_ICW4_SYSTEM_MODE, *PPIC_I8259_ICW4_SYSTEM_MODE; typedef enum _TIMER_TYPE TIMER_TYPE, *PTIMER_TYPE; typedef enum _TRAMPOLINE_TYPE TRAMPOLINE_TYPE, *PTRAMPOLINE_TYPE; /* Architecture-specific structures forward references */ typedef struct _CONTEXT CONTEXT, *PCONTEXT; typedef struct _CPU_IDENTIFICATION CPU_IDENTIFICATION, *PCPU_IDENTIFICATION; typedef struct _CPUID_REGISTERS CPUID_REGISTERS, *PCPUID_REGISTERS; typedef struct _CPUID_SIGNATURE CPUID_SIGNATURE, *PCPUID_SIGNATURE; typedef struct _FN_SAVE_FORMAT FN_SAVE_FORMAT, *PFN_SAVE_FORMAT; typedef struct _FX_SAVE_AREA FX_SAVE_AREA, *PFX_SAVE_AREA; typedef struct _FX_SAVE_FORMAT FX_SAVE_FORMAT, *PFX_SAVE_FORMAT; typedef struct _HARDWARE_LEGACY_PTE HARDWARE_LEGACY_PTE, *PHARDWARE_LEGACY_PTE; typedef struct _HARDWARE_MODERN_PTE HARDWARE_MODERN_PTE, *PHARDWARE_MODERN_PTE; typedef struct _HPET_REGISTERS HPET_REGISTERS, *PHPET_REGISTERS; typedef struct _IOAPIC_DATA IOAPIC_DATA, *PIOAPIC_DATA; typedef struct _KDESCRIPTOR KDESCRIPTOR, *PKDESCRIPTOR; typedef struct _KEXCEPTION_FRAME KEXCEPTION_FRAME, *PKEXCEPTION_FRAME; typedef struct _KGDTENTRY KGDTENTRY, *PKGDTENTRY; typedef struct _KIDTENTRY KIDTENTRY, *PKIDTENTRY; typedef struct _KIIO_ACCESS_MAP KIIO_ACCESS_MAP, *PKIIO_ACCESS_MAP; typedef struct _KPROCESSOR_BLOCK KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK; typedef struct _KPROCESSOR_CONTROL_BLOCK KPROCESSOR_CONTROL_BLOCK, *PKPROCESSOR_CONTROL_BLOCK; typedef struct _KPROCESSOR_STATE KPROCESSOR_STATE, *PKPROCESSOR_STATE; typedef struct _KSPECIAL_REGISTERS KSPECIAL_REGISTERS, *PKSPECIAL_REGISTERS; typedef struct _KSTART_FRAME KSTART_FRAME, *PKSTART_FRAME; typedef struct _KSWITCH_FRAME KSWITCH_FRAME, *PKSWITCH_FRAME; typedef struct _KTHREAD_INIT_FRAME KTHREAD_INIT_FRAME, *PKTHREAD_INIT_FRAME; typedef struct _KTRAP_FRAME KTRAP_FRAME, *PKTRAP_FRAME; typedef struct _KTSS KTSS, *PKTSS; typedef struct _MMPAGEMAP_INFO MMPAGEMAP_INFO, *PMMPAGEMAP_INFO; typedef struct _MMPFN MMPFN, *PMMPFN; typedef struct _MMPML2_PTE_HARDWARE MMPML2_PTE_HARDWARE, *PMMPML2_PTE_HARDWARE; typedef struct _MMPML2_PTE_LIST MMPML2_PTE_LIST, *PMMPML2_PTE_LIST; typedef struct _MMPML2_PTE_PROTOTYPE MMPML2_PTE_PROTOTYPE, *PMMPML2_PTE_PROTOTYPE; typedef struct _MMPML2_PTE_SOFTWARE MMPML2_PTE_SOFTWARE, *PMMPML2_PTE_SOFTWARE; typedef struct _MMPML2_PTE_SUBSECTION MMPML2_PTE_SUBSECTION, *PMMPML2_PTE_SUBSECTION; typedef struct _MMPML2_PTE_TRANSITION MMPML2_PTE_TRANSITION, *PMMPML2_PTE_TRANSITION; typedef struct _MMPML3_PTE_HARDWARE MMPML3_PTE_HARDWARE, *PMMPML3_PTE_HARDWARE; typedef struct _MMPML3_PTE_LIST MMPML3_PTE_LIST, *PMMPML3_PTE_LIST; typedef struct _MMPML3_PTE_PROTOTYPE MMPML3_PTE_PROTOTYPE, *PMMPML3_PTE_PROTOTYPE; typedef struct _MMPML3_PTE_SOFTWARE MMPML3_PTE_SOFTWARE, *PMMPML3_PTE_SOFTWARE; typedef struct _MMPML3_PTE_SUBSECTION MMPML3_PTE_SUBSECTION, *PMMPML3_PTE_SUBSECTION; typedef struct _MMPML3_PTE_TRANSITION MMPML3_PTE_TRANSITION, *PMMPML3_PTE_TRANSITION; typedef struct _POOL_DESCRIPTOR POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR; typedef struct _THREAD_ENVIRONMENT_BLOCK THREAD_ENVIRONMENT_BLOCK, *PTHREAD_ENVIRONMENT_BLOCK; typedef struct _TIMER_CAPABILITIES TIMER_CAPABILITIES, *PTIMER_CAPABILITIES; /* Unions forward references */ typedef union _APIC_BASE_REGISTER APIC_BASE_REGISTER, *PAPIC_BASE_REGISTER; typedef union _APIC_COMMAND_REGISTER APIC_COMMAND_REGISTER, *PAPIC_COMMAND_REGISTER; typedef union _APIC_LVT_REGISTER APIC_LVT_REGISTER, *PAPIC_LVT_REGISTER; typedef union _APIC_SPURIOUS_REGISTER APIC_SPURIOUS_REGISTER, *PAPIC_SPURIOUS_REGISTER; typedef union _HARDWARE_PTE HARDWARE_PTE, *PHARDWARE_PTE; typedef union _IOAPIC_REDIRECTION_REGISTER IOAPIC_REDIRECTION_REGISTER, *PIOAPIC_REDIRECTION_REGISTER; typedef union _MMPML2_PTE MMPML2_PTE, *PMMPML2_PTE; typedef union _MMPML3_PTE MMPML3_PTE, *PMMPML3_PTE; typedef union _MMPTE MMPDE, *PMMPDE; typedef union _MMPTE MMPPE, *PMMPPE; typedef union _MMPTE MMPTE, *PMMPTE; typedef union _PIC_I8259_ICW1 PIC_I8259_ICW1, *PPIC_I8259_ICW1; typedef union _PIC_I8259_ICW2 PIC_I8259_ICW2, *PPIC_I8259_ICW2; typedef union _PIC_I8259_ICW3 PIC_I8259_ICW3, *PPIC_I8259_ICW3; typedef union _PIC_I8259_ICW4 PIC_I8259_ICW4, *PPIC_I8259_ICW4; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_I686_XTSTRUCT_H */ ================================================ FILE: sdk/xtdk/iotypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/iotypes.h * DESCRIPTION: I/O related type definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_IOTYPES_H #define __XTDK_IOTYPES_H #include /* Number of PCI base address registers */ #define PCI_TYPE0_ADDRESSES 6 #define PCI_TYPE1_ADDRESSES 2 #define PCI_TYPE2_ADDRESSES 5 /* PCI maximum number of devices */ #define PCI_MAX_BRIDGE_NUMBER 255 #define PCI_MAX_DEVICES 32 #define PCI_MAX_FUNCTION 8 /* Invalid PCI vendor ID */ #define PCI_INVALID_VENDORID 0xFFFF /* PCI common config header types */ #define PCI_DEVICE_TYPE 0x00 #define PCI_BRIDGE_TYPE 0x01 #define PCI_CARDBUS_BRIDGE_TYPE 0x02 #define PCI_MULTIFUNCTION 0x80 /* PCI common config commands */ #define PCI_ENABLE_IO_SPACE 0x0001 #define PCI_ENABLE_MEMORY_SPACE 0x0002 #define PCI_ENABLE_BUS_MASTER 0x0004 #define PCI_ENABLE_SPECIAL_CYCLES 0x0008 #define PCI_ENABLE_WRITE_AND_INVALIDATE 0x0010 #define PCI_ENABLE_VGA_COMPATIBLE_PALETTE 0x0020 #define PCI_ENABLE_PARITY 0x0040 #define PCI_ENABLE_WAIT_CYCLE 0x0080 #define PCI_ENABLE_SERR 0x0100 #define PCI_ENABLE_FAST_BACK_TO_BACK 0x0200 #define PCI_DISABLE_LEVEL_INTERRUPT 0x0400 /* PCI common config statuses */ #define PCI_STATUS_INTERRUPT_PENDING 0x0008 #define PCI_STATUS_CAPABILITIES_LIST 0x0010 #define PCI_STATUS_66MHZ_CAPABLE 0x0020 #define PCI_STATUS_UDF_SUPPORTED 0x0040 #define PCI_STATUS_FAST_BACK_TO_BACK 0x0080 #define PCI_STATUS_DATA_PARITY_DETECTED 0x0100 #define PCI_STATUS_DEVSEL 0x0600 #define PCI_STATUS_SIGNALED_TARGET_ABORT 0x0800 #define PCI_STATUS_RECEIVED_TARGET_ABORT 0x1000 #define PCI_STATUS_RECEIVED_MASTER_ABORT 0x2000 #define PCI_STATUS_SIGNALED_SYSTEM_ERROR 0x4000 #define PCI_STATUS_DETECTED_PARITY_ERROR 0x8000 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* PCI bridge control registers */ typedef struct _PCI_BRIDGE_CONTROL_REGISTER { UINT Bar[2]; UCHAR PrimaryBus; UCHAR SecondaryBus; UCHAR SubordinateBus; UCHAR SecondaryLatencyTimer; UCHAR IoBase; UCHAR IoLimit; USHORT SecondaryStatus; USHORT MemoryBase; USHORT MemoryLimit; USHORT PrefetchableMemoryBase; USHORT PrefetchableMemoryLimit; UINT PrefetchableBaseUpper32; UINT PrefetchableLimitUpper32; USHORT IoBaseUpper16; USHORT IoLimitUpper16; UINT Reserved; UINT ExpansionRomBAR; UCHAR InterruptLine; UCHAR InterruptPin; USHORT BridgeControl; } PCI_BRIDGE_CONTROL_REGISTER, *PPCI_BRIDGE_CONTROL_REGISTER; /* PCI and PCI-E common header structure */ typedef struct _PCI_COMMON_HEADER { USHORT VendorId; USHORT DeviceId; USHORT Command; USHORT Status; UCHAR RevisionId; UCHAR ProgIf; UCHAR SubClass; UCHAR BaseClass; UCHAR CacheLineSize; UCHAR LatencyTimer; UCHAR HeaderType; UCHAR BIST; union { struct _PCI_TYPE0_HEADER { ULONG BaseAddresses[PCI_TYPE0_ADDRESSES]; ULONG CIS; USHORT SubVendorId; USHORT SubSystemId; ULONG ROMBaseAddress; UCHAR CapabilitiesPtr; UCHAR Reserved1[3]; ULONG Reserved2; UCHAR InterruptLine; UCHAR InterruptPin; UCHAR MinimumGrant; UCHAR MaximumLatency; } type0; struct _PCI_TYPE1_HEADER { ULONG BaseAddresses[PCI_TYPE1_ADDRESSES]; UCHAR PrimaryBus; UCHAR SecondaryBus; UCHAR SubordinateBus; UCHAR SecondaryLatency; UCHAR IOBase; UCHAR IOLimit; USHORT SecondaryStatus; USHORT MemoryBase; USHORT MemoryLimit; USHORT PrefetchBase; USHORT PrefetchLimit; ULONG PrefetchBaseUpper32; ULONG PrefetchLimitUpper32; USHORT IOBaseUpper16; USHORT IOLimitUpper16; UCHAR CapabilitiesPtr; UCHAR Reserved1[3]; ULONG ROMBaseAddress; UCHAR InterruptLine; UCHAR InterruptPin; USHORT BridgeControl; } type1; struct _PCI_TYPE2_HEADER { ULONG SocketRegistersBaseAddress; UCHAR CapabilitiesPtr; UCHAR Reserved; USHORT SecondaryStatus; UCHAR PrimaryBus; UCHAR SecondaryBus; UCHAR SubordinateBus; UCHAR SecondaryLatency; struct { ULONG Base; ULONG Limit; } Range[PCI_TYPE2_ADDRESSES - 1]; UCHAR InterruptLine; UCHAR InterruptPin; USHORT BridgeControl; } type2; } u; } PCI_COMMON_HEADER, *PPCI_COMMON_HEADER; /* PCI and PCI-E common config structure */ typedef struct _PCI_COMMON_CONFIG { PCI_COMMON_HEADER PciHeader; UCHAR DeviceSpecific[192]; } PCI_COMMON_CONFIG, *PPCI_COMMON_CONFIG; /* PCI device header type region structure */ typedef struct _PCI_DEVICE_HEADER_TYPE_REGION { UINT Bar[6]; UINT CISPtr; USHORT SubsystemVendorID; USHORT SubsystemID; UINT ExpansionRomBar; UINT Reserved[2]; UCHAR InterruptLine; UCHAR InterruptPin; UCHAR MinGnt; UCHAR MaxLat; } PCI_DEVICE_HEADER_TYPE_REGION, *PPCI_DEVICE_HEADER_TYPE_REGION; /* PCI device independent region structure */ typedef struct _PCI_DEVICE_INDEPENDENT_REGION { USHORT VendorId; USHORT DeviceId; USHORT Command; USHORT Status; UCHAR RevisionID; UCHAR ClassCode[3]; UCHAR CacheLineSize; UCHAR LaytencyTimer; UCHAR HeaderType; UCHAR BIST; } PCI_DEVICE_INDEPENDENT_REGION, *PPCI_DEVICE_INDEPENDENT_REGION; /* PCI device type 0 structure */ typedef struct _PCI_TYPE0_DEVICE { PCI_DEVICE_INDEPENDENT_REGION Hdr; PCI_DEVICE_HEADER_TYPE_REGION Device; } PCI_TYPE0_DEVICE, *PPCI_TYPE0_DEVICE; /* PCI device type 1 structure */ typedef struct _PCI_TYPE1_DEVICE { PCI_DEVICE_INDEPENDENT_REGION Hdr; PCI_BRIDGE_CONTROL_REGISTER Bridge; } PCI_TYPE1_DEVICE, *PPCI_TYPE1_DEVICE; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_IOTYPES_H */ ================================================ FILE: sdk/xtdk/kdfuncs.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/kdfuncs.h * DESCRIPTION: XTOS kernel debugger routine definitions * DEVELOPERS: Aiken Harris */ #ifndef __XTDK_KDFUNCS_H #define __XTDK_KDFUNCS_H #include #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Kernel debugger routines forward references */ XTCLINK XTCDECL VOID DbgPrint(PCWSTR Format, ...); #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_KDFUNCS_H */ ================================================ FILE: sdk/xtdk/kdtypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/kdtypes.h * DESCRIPTION: Kernel Debugger data structures * DEVELOPERS: Aiken Harris */ #ifndef __XTDK_KDTYPES_H #define __XTDK_KDTYPES_H #include #include #include /* Number of debug providers */ #define KDBG_PROVIDERS_COUNT 2 /* Debug providers bitmask definitions */ #define DEBUG_PROVIDER_COMPORT 0x00000001 #define DEBUG_PROVIDER_FRAMEBUFFER 0x00000002 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Kernel routine callbacks */ typedef XTSTATUS (XTAPI *PKD_INIT_ROUTINE)(); typedef VOID (*PKD_PRINT_ROUTINE)(IN PCWSTR Format, IN ...); /* Debug mode structure definition */ typedef struct _KD_DEBUG_MODE { BOOLEAN Enabled; ULONG Mode; ULONG ComPortAddress; ULONG ComPortNumber; ULONG ComPortBaudRate; } KD_DEBUG_MODE, *PKD_DEBUG_MODE; /* Kernel debugger dispatch table structure definition */ typedef struct _KD_DISPATCH_TABLE { LIST_ENTRY ListEntry; RTL_PRINT_CONTEXT PrintContext; } KD_DISPATCH_TABLE, *PKD_DISPATCH_TABLE; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_KDTYPES_H */ ================================================ FILE: sdk/xtdk/kefuncs.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/kefuncs.h * DESCRIPTION: XTOS kernel services routine definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_KEFUNCS_H #define __XTDK_KEFUNCS_H #include #include #include #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Kernel services routines forward references */ XTCLINK XTFASTCALL VOID KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_LEVEL LockLevel); XTCLINK XTFASTCALL VOID KeAcquireSpinLock(IN OUT PKSPIN_LOCK SpinLock); XTCLINK XTAPI XTSTATUS KeAcquireSystemResource(IN SYSTEM_RESOURCE_TYPE ResourceType, OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader); XTCLINK XTAPI BOOLEAN KeCancelTimer(IN PKTIMER Timer); XTCLINK XTFASTCALL KRUNLEVEL KeGetCurrentRunLevel(VOID); XTCLINK XTAPI XTSTATUS KeGetSystemResource(IN SYSTEM_RESOURCE_TYPE ResourceType, OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader); XTCLINK XTAPI BOOLEAN KeGetTimerState(IN PKTIMER Timer); XTCLINK XTAPI VOID KeInitializeApc(IN PKAPC Apc, IN PKTHREAD Thread, IN KAPC_ENVIRONMENT Environment, IN PKKERNEL_ROUTINE KernelRoutine, IN PKRUNDOWN_ROUTINE RundownRoutine, IN PKNORMAL_ROUTINE NormalRoutine, IN KPROCESSOR_MODE ApcMode, IN PVOID Context); XTCLINK XTAPI VOID KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DpcRoutine, IN PVOID DpcContext); XTCLINK XTAPI VOID KeInitializeSemaphore(IN PKSEMAPHORE Semaphore, IN LONG Count, IN LONG Limit); XTCLINK XTAPI VOID KeInitializeSpinLock(IN PKSPIN_LOCK SpinLock); XTCLINK XTAPI VOID KeInitializeThreadedDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DpcRoutine, IN PVOID DpcContext); XTCLINK XTAPI VOID KeInitializeTimer(OUT PKTIMER Timer, IN KTIMER_TYPE Type); XTCLINK XTFASTCALL VOID KeLowerRunLevel(IN KRUNLEVEL RunLevel); XTCLINK XTFASTCALL KRUNLEVEL KeRaiseRunLevel(IN KRUNLEVEL RunLevel); XTCLINK XTAPI LONG KeReadSemaphoreState(IN PKSEMAPHORE Semaphore); XTCLINK XTAPI LONG KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait); XTCLINK XTFASTCALL VOID KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_LEVEL LockLevel); XTCLINK XTFASTCALL VOID KeReleaseSpinLock(IN OUT PKSPIN_LOCK SpinLock); XTCLINK XTAPI VOID KeReleaseSystemResource(IN PSYSTEM_RESOURCE_HEADER ResourceHeader); XTCLINK XTAPI VOID KeSetTargetProcessorDpc(IN PKDPC Dpc, IN CCHAR Number); XTCLINK XTAPI VOID KeSetTimeIncrement(IN ULONG MaxIncrement, IN ULONG MinIncrement); XTCLINK XTAPI VOID KeSetTimer(IN PKTIMER Timer, IN LARGE_INTEGER DueTime, IN LONG Period, IN PKDPC Dpc); XTCLINK XTAPI VOID KeSignalCallDpcDone(IN PVOID SystemArgument); XTCLINK XTAPI BOOLEAN KeSignalCallDpcSynchronize(IN PVOID SystemArgument); #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_KEFUNCS_H */ ================================================ FILE: sdk/xtdk/ketypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/ketypes.h * DESCRIPTION: XT kernel core structures definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_KETYPES_H #define __XTDK_KETYPES_H #include #include #include #include #include ARCH_HEADER(xtstruct.h) /* Exception types and handling mechanisms */ #define EXCEPTION_CONTINUE_SEARCH 0x00 #define EXCEPTION_EXECUTE_HANDLER 0x01 #define EXCEPTION_CONTINUE_EXECUTION 0xFF /* Maximum number of exception parameters */ #define EXCEPTION_MAXIMUM_PARAMETERS 15 /* APC pending state length */ #define KAPC_STATE_LENGTH (FIELD_OFFSET(KAPC_STATE, UserApcPending) + sizeof(BOOLEAN)) /* Kernel service descriptor tables count */ #define KSERVICE_TABLES_COUNT 4 /* Timer length */ #define KTIMER_LENGTH (FIELD_OFFSET(KTIMER, Period) + sizeof(LONG)) /* Kernel builtin wait blocks */ #define EVENT_WAIT_BLOCK 2 #define KTHREAD_WAIT_BLOCK 3 #define KTIMER_WAIT_BLOCK 3 #define SEMAPHORE_WAIT_BLOCK 2 /* Quantum values */ #define READY_SKIP_QUANTUM 2 #define THREAD_QUANTUM 6 /* Thread priority levels */ #define THREAD_LOW_PRIORITY 0 #define THREAD_LOW_REALTIME_PRIORITY 16 #define THREAD_HIGH_PRIORITY 31 #define THREAD_MAXIMUM_PRIORITY 32 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Adjust reason */ typedef enum _ADJUST_REASON { AdjustNone = 0, AdjustUnwait = 1, AdjustBoost = 2 } ADJUST_REASON, *PADJUST_REASON; /* Exception disposition return values */ typedef enum _EXCEPTION_DISPOSITION { ExceptionContinueExecution, ExceptionContinueSearch, ExceptionNestedException, ExceptionCollidedUnwind, } EXCEPTION_DISPOSITION, *PEXCEPTION_DISPOSITION; /* APC environment types */ typedef enum _KAPC_ENVIRONMENT { OriginalApcEnvironment, AttachedApcEnvironment, CurrentApcEnvironment, InsertApcEnvironment } KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT; /* DPC importance enumeration list */ typedef enum _KDPC_IMPORTANCE { LowImportance, MediumImportance, HighImportance, MediumHighImportance } KDPC_IMPORTANCE, *PKDPC_IMPORTANCE; /* Event types list */ typedef enum _KEVENT_TYPE { NotificationEvent, SynchronizationEvent } KEVENT_TYPE, *PKEVENT_TYPE; /* Kernel objects */ typedef enum _KOBJECTS { EventNotificationObject = 0, EventSynchronizationObject = 1, MutantObject = 2, ProcessObject = 3, QueueObject = 4, SemaphoreObject = 5, ThreadObject = 6, GateObject = 7, TimerNotificationObject = 8, TimerSynchronizationObject = 9, Spare2Object = 10, Spare3Object = 11, Spare4Object = 12, Spare5Object = 13, Spare6Object = 14, Spare7Object = 15, Spare8Object = 16, Spare9Object = 17, ApcObject = 18, DpcObject = 19, DeviceQueueObject = 20, EventPairObject = 21, InterruptObject = 22, ProfileObject = 23, ThreadedDpcObject = 24, MaximumKernelObject = 25 } KOBJECTS, *PKOBJECTS; /* Process states */ typedef enum _KPROCESS_STATE { ProcessInMemory, ProcessOutOfMemory, ProcessInTransition, ProcessOutTransition, ProcessInSwap, ProcessOutSwap } KPROCESS_STATE, *PKPROCESS_STATE; /* Kernel profiling sources */ typedef enum _KPROFILE_SOURCE { ProfileTime, ProfileAlignmentFixup, ProfileTotalIssues, ProfilePipelineDry, ProfileLoadInstructions, ProfilePipelineFrozen, ProfileBranchInstructions, ProfileTotalNonissues, ProfileDcacheMisses, ProfileIcacheMisses, ProfileCacheMisses, ProfileBranchMispredictions, ProfileStoreInstructions, ProfileFpInstructions, ProfileIntegerInstructions, Profile2Issue, Profile3Issue, Profile4Issue, ProfileSpecialInstructions, ProfileTotalCycles, ProfileIcacheIssues, ProfileDcacheAccesses, ProfileMemoryBarrierCycles, ProfileLoadLinkedIssues, ProfileXtKernel, ProfileMaximum } KPROFILE_SOURCE, *PKPROFILE_SOURCE; /* Thread state */ typedef enum _KTHREAD_STATE { Initialized, Ready, Running, Standby, Terminated, Waiting, Transition, DeferredReady } KTHREAD_STATE, *PKTHREAD_STATE; /* Spin lock queue levels */ typedef enum _KSPIN_LOCK_QUEUE_LEVEL { DispatcherLock, ExpansionLock, PfnLock, SystemSpaceLock, VacbLock, MasterLock, NonPagedAllocPoolLock, IoCancelLock, WorkQueueLock, IoVpbLock, IoDatabaseLock, IoCompletionLock, FileSystemLock, AfdWorkQueueLock, BcbLock, NonPagedPoolLock, ReservedSystemLock, TimerTableLock, MaximumLock } KSPIN_LOCK_QUEUE_LEVEL, *PKSPIN_LOCK_QUEUE_LEVEL; /* Timer type */ typedef enum _KTIMER_TYPE { NotificationTimer, SynchronizationTimer } KTIMER_TYPE, *PKTIMER_TYPE; /* APC Types */ typedef enum _MODE { KernelMode, UserMode, MaximumMode } MODE, *PMODE; /* System resource types */ typedef enum _SYSTEM_RESOURCE_TYPE { SystemResourceInvalid, SystemResourceAcpi, SystemResourceFrameBuffer } SYSTEM_RESOURCE_TYPE, *PSYSTEM_RESOURCE_TYPE; /* Wait type */ typedef enum _WAIT_TYPE { WaitAll, WaitAny } WAIT_TYPE, *PWAIT_TYPE; /* Kernel UBSAN data types enumeration list */ typedef enum _KUBSAN_DATA_TYPE { DataTypeInt, DataTypeFloat, DataTypeUnknown = 0xFFFF } KUBSAN_DATA_TYPE, *PKUBSAN_DATA_TYPE; /* Kernel routine callbacks */ typedef EXCEPTION_DISPOSITION (XTCDECL *PEXCEPTION_ROUTINE)(IN PEXCEPTION_RECORD ExceptionRecord, IN PVOID EstablisherFrame, IN OUT PCONTEXT ContextRecord, IN OUT PVOID DispatcherContext); typedef VOID (XTAPI *PKDEFERRED_ROUTINE)(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); typedef VOID (XTAPI *PKNORMAL_ROUTINE)(IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); typedef VOID (XTAPI *PKKERNEL_ROUTINE)(IN PKAPC Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2); typedef VOID (XTAPI *PKRUNDOWN_ROUTINE)(IN PKAPC Apc); typedef VOID (XTCDECL *PKSTART_ROUTINE)(IN PVOID StartContext); typedef VOID (XTCDECL *PKSYSTEM_ROUTINE)(IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext); /* Exception record structure definition */ typedef struct _EXCEPTION_RECORD { XTSTATUS ExceptionCode; ULONG ExceptionFlags; PEXCEPTION_RECORD ExceptionRecord; PVOID ExceptionAddress; ULONG NumberParameters; ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; } EXCEPTION_RECORD, *PEXCEPTION_RECORD; /* Asynchronous Procedure Call (APC) object structure definition */ typedef struct _KAPC { UCHAR Type; UCHAR SpareByte0; UCHAR Size; UCHAR SpareByte1; ULONG SpareLong0; PKTHREAD Thread; LIST_ENTRY ApcListEntry; PKKERNEL_ROUTINE KernelRoutine; PKRUNDOWN_ROUTINE RundownRoutine; PKNORMAL_ROUTINE NormalRoutine; PVOID NormalContext; PVOID SystemArgument1; PVOID SystemArgument2; CHAR ApcStateIndex; KPROCESSOR_MODE ApcMode; BOOLEAN Inserted; } KAPC, *PKAPC; /* Deferred Procedure Call (DPC) object structure definition */ typedef struct _KDPC { UCHAR Type; UCHAR Importance; UCHAR Number; UCHAR Expedite; LIST_ENTRY DpcListEntry; PKDEFERRED_ROUTINE DeferredRoutine; PVOID DeferredContext; PVOID SystemArgument1; PVOID SystemArgument2; PVOID DpcData; } KDPC, *PKDPC; /* DPC data structure definition */ typedef struct _KDPC_DATA { LIST_ENTRY DpcListHead; KSPIN_LOCK DpcLock; VOLATILE ULONG DpcQueueDepth; ULONG DpcCount; } KDPC_DATA, *PKDPC_DATA; /* Event object structure definition */ typedef struct _KEVENT { DISPATCHER_HEADER Header; } KEVENT, *PKEVENT; /* Exception registration record structure definition */ typedef struct _EXCEPTION_REGISTRATION_RECORD { PEXCEPTION_REGISTRATION_RECORD Next; PEXCEPTION_ROUTINE Handler; } EXCEPTION_REGISTRATION_RECORD, *PEXCEPTION_REGISTRATION_RECORD; /* APC state structure definition */ typedef struct _KAPC_STATE { LIST_ENTRY ApcListHead[MaximumMode]; PKPROCESS Process; BOOLEAN KernelApcInProgress; BOOLEAN KernelApcPending; BOOLEAN UserApcPending; } KAPC_STATE, *PKAPC_STATE; /* Event gate structure definition */ typedef struct _KGATE { DISPATCHER_HEADER Header; } KGATE, *PKGATE; /* Semaphore object structure definition */ typedef struct _KSEMAPHORE { DISPATCHER_HEADER Header; LONG Limit; } KSEMAPHORE, *PKSEMAPHORE; /* Per processor lock queue structure definition */ typedef struct _KSPIN_LOCK_QUEUE { PKSPIN_LOCK_QUEUE Next; PKSPIN_LOCK Lock; } KSPIN_LOCK_QUEUE, *PKSPIN_LOCK_QUEUE; /* Per processor lock queue handle structure definition */ typedef struct _KLOCK_QUEUE_HANDLE { KSPIN_LOCK_QUEUE LockQueue; KRUNLEVEL OldRunLevel; } KLOCK_QUEUE_HANDLE, *PKLOCK_QUEUE_HANDLE; /* Queue object structure definition */ typedef struct _KQUEUE { DISPATCHER_HEADER Header; LIST_ENTRY EntryListHead; ULONG CurrentCount; ULONG MaximumCount; LIST_ENTRY ThreadListHead; } KQUEUE, *PKQUEUE; /* Kernel service table descriptor */ typedef struct _KSERVICE_DESCRIPTOR_TABLE { PULONG_PTR Base; PULONG Count; ULONG Limit; PUCHAR Number; } KSERVICE_DESCRIPTOR_TABLE, *PKSERVICE_DESCRIPTOR_TABLE; /* Timer object structure definition */ typedef struct _KTIMER { DISPATCHER_HEADER Header; ULARGE_INTEGER DueTime; LIST_ENTRY TimerListEntry; PKDPC Dpc; LONG Period; } KTIMER, *PKTIMER; /* Wait block structure definition */ typedef struct _KWAIT_BLOCK { LIST_ENTRY WaitListEntry; PKTHREAD Thread; PVOID Object; PKWAIT_BLOCK *NextWaitBlock; USHORT WaitKey; UCHAR WaitType; UCHAR SpareByte; LONG SpareLong; } KWAIT_BLOCK, *PKWAIT_BLOCK; /* XT Thread Information Block (TIB) definition */ typedef struct _THREAD_INFORMATION_BLOCK { PEXCEPTION_REGISTRATION_RECORD ExceptionList; PVOID StackBase; PVOID StackLimit; PVOID SubSystemTib; PVOID ArbitraryUserPointer; PTHREAD_INFORMATION_BLOCK Self; } THREAD_INFORMATION_BLOCK, *PTHREAD_INFORMATION_BLOCK; /* Process control block structure definition */ typedef struct _KPROCESS { DISPATCHER_HEADER Header; LIST_ENTRY ProfileListHead; ULONG_PTR DirectoryTable[2]; USHORT IopmOffset; UCHAR Iopl; VOLATILE KAFFINITY ActiveProcessors; ULONG KernelTime; ULONG UserTime; LIST_ENTRY ReadyListHead; SINGLE_LIST_ENTRY SwapListEntry; PVOID VdmTrapHandler; LIST_ENTRY ThreadListHead; KSPIN_LOCK ProcessLock; KAFFINITY Affinity; union { struct { BOOLEAN AutoAlignment; BOOLEAN DisableBoost; BOOLEAN DisableQuantum; LONG ReservedFlags:29; }; LONG ProcessFlags; }; ULONG_PTR StackCount; SCHAR BasePriority; SCHAR Quantum; UCHAR State; UCHAR ThreadSeed; UCHAR PowerState; UCHAR IdealNode; UCHAR Spare; } KPROCESS, *PKPROCESS; /* System Time structure definition */ typedef struct _KSYSTEM_TIME { ULONG LowPart; LONG High1Part; LONG High2Part; } KSYSTEM_TIME, *PKSYSTEM_TIME; /* Kernel Shared Data (KSD) structure definition */ typedef struct _KSHARED_DATA { VOLATILE KSYSTEM_TIME InterruptTime; VOLATILE KSYSTEM_TIME SystemTime; VOLATILE KSYSTEM_TIME TickCount; ULONG XtMajorVersion; ULONG XtMinorVersion; WCHAR XtBuild[8]; WCHAR XtBuildHash[11]; WCHAR XtArchitecture[8]; WCHAR XtDate[9]; WCHAR XtFullDate[25]; } KSHARED_DATA, *PKSHARED_DATA; /* Thread control block structure definition */ typedef struct _KTHREAD { DISPATCHER_HEADER Header; LIST_ENTRY MutantListHead; PVOID InitialStack; PVOID KernelStack; PVOID StackBase; PVOID StackLimit; KSPIN_LOCK ThreadLock; ULONG ContextSwitches; VOLATILE UCHAR State; UCHAR NpxState; KRUNLEVEL WaitRunLevel; KPROCESSOR_MODE WaitMode; PTHREAD_ENVIRONMENT_BLOCK EnvironmentBlock; union { KAPC_STATE ApcState; struct { UCHAR ApcStateFill[KAPC_STATE_LENGTH]; BOOLEAN ApcQueueable; VOLATILE UCHAR NextProcessor; VOLATILE UCHAR DeferredProcessor; UCHAR AdjustReason; SCHAR AdjustIncrement; }; }; KSPIN_LOCK ApcQueueLock; LONG_PTR WaitStatus; PKWAIT_BLOCK WaitBlockList; BOOLEAN Alertable; BOOLEAN WaitNext; UCHAR WaitReason; SCHAR Priority; UCHAR StackSwap; VOLATILE UCHAR SwapBusy; BOOLEAN Alerted[MaximumMode]; union { LIST_ENTRY WaitListEntry; SINGLE_LIST_ENTRY SwapListEntry; }; PKQUEUE Queue; ULONG WaitTime; union { struct { SHORT KernelApcDisable; SHORT SpecialApcDisable; }; ULONG CombinedApcDisable; }; KTIMER Timer; KWAIT_BLOCK WaitBlock[KTHREAD_WAIT_BLOCK + 1]; LIST_ENTRY QueueListEntry; UCHAR ApcStateIndex; BOOLEAN Preempted; BOOLEAN ProcessReadyQueue; BOOLEAN KernelStackResident; CHAR Saturation; UCHAR IdealProcessor; SCHAR BasePriority; UCHAR Spare4; SCHAR PriorityDecrement; SCHAR Quantum; BOOLEAN SystemAffinityActive; CHAR PreviousMode; UCHAR ResourceIndex; UCHAR DisableBoost; KAFFINITY UserAffinity; PKPROCESS Process; KAFFINITY Affinity; PVOID ServiceTable; PKAPC_STATE ApcStatePointer[2]; KAPC_STATE SavedApcState; PVOID CallbackStack; PVOID SubSystemThread; PKTRAP_FRAME TrapFrame; ULONG KernelTime; ULONG UserTime; KAPC SuspendApc; KSEMAPHORE SuspendSemaphore; PVOID TlsArray; PVOID LegoData; LIST_ENTRY ThreadListEntry; UCHAR LargeStack; UCHAR PowerState; UCHAR NpxIrql; UCHAR Spare5; BOOLEAN AutoAlignment; UCHAR Iopl; CCHAR FreezeCount; CCHAR SuspendCount; UCHAR Spare0[1]; UCHAR UserIdealProcessor; UCHAR Spare2[3]; ULONG KernelLimit; BOOLEAN StackResident; } KTHREAD, *PKTHREAD; /* System resource common header structure definition */ typedef struct _SYSTEM_RESOURCE_HEADER { LIST_ENTRY ListEntry; SYSTEM_RESOURCE_TYPE ResourceType; BOOLEAN ResourceLocked; ULONG ResourceSize; PVOID PhysicalAddress; PVOID VirtualAddress; } SYSTEM_RESOURCE_HEADER, *PSYSTEM_RESOURCE_HEADER; /* ACPI system resource structure definition */ typedef struct _SYSTEM_RESOURCE_ACPI { SYSTEM_RESOURCE_HEADER Header; PVOID ApicBase; } SYSTEM_RESOURCE_ACPI, *PSYSTEM_RESOURCE_ACPI; /* FrameBuffer system resource structure definition */ typedef struct _SYSTEM_RESOURCE_FRAMEBUFFER { SYSTEM_RESOURCE_HEADER Header; ULONG_PTR BufferSize; UINT Width; UINT Height; UINT Depth; UINT PixelsPerScanLine; UINT BitsPerPixel; UINT Pitch; PVOID Font; struct { USHORT BlueShift; USHORT BlueSize; USHORT GreenShift; USHORT GreenSize; USHORT RedShift; USHORT RedSize; USHORT ReservedShift; USHORT ReservedSize; } Pixels; } SYSTEM_RESOURCE_FRAMEBUFFER, *PSYSTEM_RESOURCE_FRAMEBUFFER; /* Kernel UBSAN source location structure definition */ typedef struct _KUBSAN_SOURCE_LOCATION { PCCHAR FileName; union { ULONG Reported; struct { UINT Line; UINT Column; }; }; } KUBSAN_SOURCE_LOCATION, *PKUBSAN_SOURCE_LOCATION; /* Kernel UBSAN type descriptor structure definition */ typedef struct _KUBSAN_TYPE_DESCRIPTOR { USHORT DataType; USHORT TypeInfo; CHAR TypeName[1]; } KUBSAN_TYPE_DESCRIPTOR, *PKUBSAN_TYPE_DESCRIPTOR; /* Kernel UBSAN float cast overflow data structure definition */ typedef struct _KUBSAN_FLOAT_CAST_OVERFLOW_DATA { KUBSAN_SOURCE_LOCATION Location; PKUBSAN_TYPE_DESCRIPTOR LhsType; PKUBSAN_TYPE_DESCRIPTOR RhsType; } KUBSAN_FLOAT_CAST_OVERFLOW_DATA, *PKUBSAN_FLOAT_CAST_OVERFLOW_DATA; /* Kernel UBSAN function type mismatch data structure definition */ typedef struct _KUBSAN_FUNCTION_TYPE_MISMATCH_DATA { KUBSAN_SOURCE_LOCATION Location; PKUBSAN_TYPE_DESCRIPTOR Type; } KUBSAN_FUNCTION_TYPE_MISMATCH_DATA, *PKUBSAN_FUNCTION_TYPE_MISMATCH_DATA; /* Kernel UBSAN invalid builtin data structure definition */ typedef struct _KUBSAN_INVALID_BUILTIN_DATA { KUBSAN_SOURCE_LOCATION Location; UCHAR Kind; } KUBSAN_INVALID_BUILTIN_DATA, *PKUBSAN_INVALID_BUILTIN_DATA; /* Kernel UBSAN shift out of bounds data structure definition */ typedef struct _KUBSAN_SHIFT_OUT_OF_BOUNDS_DATA { KUBSAN_SOURCE_LOCATION Location; PKUBSAN_TYPE_DESCRIPTOR LhsType; PKUBSAN_TYPE_DESCRIPTOR RhsType; } KUBSAN_SHIFT_OUT_OF_BOUNDS_DATA, *PKUBSAN_SHIFT_OUT_OF_BOUNDS_DATA; /* Kernel UBSAN out of bounds data structure definition */ typedef struct _KUBSAN_OUT_OF_BOUNDS_DATA { KUBSAN_SOURCE_LOCATION Location; PKUBSAN_TYPE_DESCRIPTOR ArrayType; PKUBSAN_TYPE_DESCRIPTOR IndexType; } KUBSAN_OUT_OF_BOUNDS_DATA, *PKUBSAN_OUT_OF_BOUNDS_DATA; /* Kernel UBSAN overflow data structure definition */ typedef struct _KUBSAN_OVERFLOW_DATA { KUBSAN_SOURCE_LOCATION Location; PKUBSAN_TYPE_DESCRIPTOR Type; } KUBSAN_OVERFLOW_DATA, *PKUBSAN_OVERFLOW_DATA; /* Kernel UBSAN type mismatch data structure definition */ typedef struct _KUBSAN_TYPE_MISMATCH_DATA { KUBSAN_SOURCE_LOCATION Location; PKUBSAN_TYPE_DESCRIPTOR Type; ULONG Alignment; UCHAR TypeCheckKind; } KUBSAN_TYPE_MISMATCH_DATA, *PKUBSAN_TYPE_MISMATCH_DATA; /* Kernel UBSAN type mismatch data structure definition */ typedef struct _KUBSAN_TYPE_MISMATCH_DATA_V1 { KUBSAN_SOURCE_LOCATION Location; PKUBSAN_TYPE_DESCRIPTOR Type; UCHAR LogAlignment; UCHAR TypeCheckKind; } KUBSAN_TYPE_MISMATCH_DATA_V1, *PKUBSAN_TYPE_MISMATCH_DATA_V1; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_KEFUNCS_H */ ================================================ FILE: sdk/xtdk/ldrtypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/ldrtypes.h * DESCRIPTION: Loader structures definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_LDRTYPES_H #define __XTDK_LDRTYPES_H #include /* Loader Data Table Entry Flags */ #define LDR_DTE_STATIC_LINK 0x00000002 #define LDR_DTE_IMAGE_DLL 0x00000004 #define LDR_DTE_SHIMENG_SUPPRESSED_ENTRY 0x00000008 #define LDR_DTE_IMAGE_INTEGRITY_FORCED 0x00000020 #define LDR_DTE_LOAD_IN_PROGRESS 0x00001000 #define LDR_DTE_UNLOAD_IN_PROGRESS 0x00002000 #define LDR_DTE_ENTRY_PROCESSED 0x00004000 #define LDR_DTE_ENTRY_INSERTED 0x00008000 #define LDR_DTE_CURRENT_LOAD 0x00010000 #define LDR_DTE_FAILED_BUILTIN_LOAD 0x00020000 #define LDR_DTE_DONT_CALL_FOR_THREADS 0x00040000 #define LDR_DTE_PROCESS_ATTACH_CALLED 0x00080000 #define LDR_DTE_DEBUG_SYMBOLS_LOADED 0x00100000 #define LDR_DTE_IMAGE_NOT_AT_BASE 0x00200000 #define LDR_DTE_COR_IMAGE 0x00400000 #define LDR_DTE_COR_OWNS_UNMAP 0x00800000 #define LDR_DTE_SYSTEM_MAPPED 0x01000000 #define LDR_DTE_IMAGE_VERIFYING 0x02000000 #define LDR_DTE_DRIVER_DEPENDENT_DLL 0x04000000 #define LDR_DTE_ENTRY_NATIVE 0x08000000 #define LDR_DTE_REDIRECTED 0x10000000 #define LDR_DTE_NON_PAGED_DEBUG_INFO 0x20000000 #define LDR_DTE_MM_LOADED 0x40000000 #define LDR_DTE_COMPAT_DATABASE_PROCESSED 0x80000000 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Loader data table entry */ typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; USHORT LoadCount; USHORT TlsIndex; union { LIST_ENTRY HashLinks; struct { PVOID SectionPointer; ULONG CheckSum; }; }; union { ULONG TimeDateStamp; PVOID LoadedImports; }; PVOID EntryPointActivationContext; PVOID PatchInformation; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_LDRTYPES_H */ ================================================ FILE: sdk/xtdk/mmfuncs.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/mmfuncs.h * DESCRIPTION: XTOS memory manager routine definitions * DEVELOPERS: Aiken Harris */ #ifndef __XTDK_MMFUNCS_H #define __XTDK_MMFUNCS_H #include #include #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Memory manager routines forward references */ XTAPI XTSTATUS MmAllocatePool(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, OUT PVOID *Memory); XTAPI XTSTATUS MmAllocatePoolWithTag(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, OUT PVOID *Memory, IN ULONG Tag); XTAPI XTSTATUS MmFreePool(IN PVOID VirtualAddress); XTAPI XTSTATUS MmFreePoolWithTag(IN PVOID VirtualAddress, IN ULONG Tag); #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_MMFUNCS_H */ ================================================ FILE: sdk/xtdk/mmtypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/mmtypes.h * DESCRIPTION: Memory management data structures * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #ifndef __XTDK_MMTYPES_H #define __XTDK_MMTYPES_H #include #include ARCH_HEADER(xtstruct.h) /* Number of hyper space pages */ #define MM_HYPERSPACE_PAGE_COUNT 255 /* Number of free page list heads */ #define MM_MAX_FREE_PAGE_LIST_HEADS 4 /* Number of paging colors */ #define MM_PAGING_COLORS 64 /* PTE frame mask definition */ #define MM_PFN_PTE_FRAME (((ULONG_PTR)1 << MM_PTE_FRAME_BITS) - 1) /* Memory manager pool type mask definition */ #define MM_POOL_TYPE_MASK 1 /* Bad pool caller reasons */ #define MM_POOL_INVALID_ALLOC_RUNLEVEL 8 #define MM_POOL_INVALID_FREE_RUNLEVEL 9 /* Pool flags */ #define MM_POOL_BIG_ALLOCATIONS_ENTRY_FREE 0x1 #define MM_POOL_PROTECTED 0x80000000 #define MM_POOL_RAISE_EXCEPTION 0x10 /* Number of reserved zeroed PTEs */ #define MM_RESERVED_ZERO_PTES 32 /* Memory Manager Protection Bits */ #define MM_ZERO_ACCESS 0 #define MM_READONLY 1 #define MM_EXECUTE 2 #define MM_EXECUTE_READ 3 #define MM_READWRITE 4 #define MM_WRITECOPY 5 #define MM_EXECUTE_READWRITE 6 #define MM_EXECUTE_WRITECOPY 7 #define MM_PROTECT_ACCESS 7 /* Protection field shift */ #define MM_PROTECT_FIELD_SHIFT 5 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Memory manager page lists */ typedef enum _MMPAGELISTS { ZeroedPageList = 0, FreePageList = 1, StandbyPageList = 2, ModifiedPageList = 3, ModifiedReadOnlyPageList = 4, BadPageList = 5, ActiveAndValid = 6, TransitionPage = 7 } MMPAGELISTS, *PMMPAGELISTS; /* Page cache attributes */ typedef enum _MMPFN_CACHE_ATTRIBUTE { PfnNonCached, PfnCached, PfnWriteCombined, PfnNotMapped } MMPFN_CACHE_ATTRIBUTE, *PMMPFN_CACHE_ATTRIBUTE; /* Memory Manager pool types */ typedef enum _MMPOOL_TYPE { NonPagedPool = 0, PagedPool = 1, NonPagedPoolMustSucceed = 2, NonPagedPoolCacheAligned = 4, PagedPoolCacheAligned = 5, NonPagedPoolCacheAlignedMustSucceed = 6, MaxPoolType = 7, NonPagedPoolSession = 32, PagedPoolSession = 33, NonPagedPoolMustSucceedSession = 34, NonPagedPoolCacheAlignedSession = 36, PagedPoolCacheAlignedSession = 37, NonPagedPoolCacheAlignedMustSucceedSession = 38 } MMPOOL_TYPE, *PMMPOOL_TYPE; /* Page table pool types */ typedef enum _MMSYSTEM_PTE_POOL_TYPE { SystemPteSpace, NonPagedPoolExpansion, MaximumPtePoolTypes } MMSYSTEM_PTE_POOL_TYPE, *PMMSYSTEM_PTE_POOL_TYPE; /* Page map routines structure definition */ typedef CONST STRUCT _CMMPAGEMAP_ROUTINES { VOID (XTAPI *ClearPte)(PHARDWARE_PTE PtePointer); BOOLEAN (XTAPI *PteValid)(PHARDWARE_PTE PtePointer); VOID (XTAPI *SetPteCaching)(PHARDWARE_PTE PtePointer, BOOLEAN CacheDisable, BOOLEAN WriteThrough); VOID (XTAPI *SetPte)(PHARDWARE_PTE PtePointer, PFN_NUMBER PageFrameNumber, BOOLEAN Writable); } CMMPAGEMAP_ROUTINES, *PCMMPAGEMAP_ROUTINES; /* Color tables structure definition */ typedef struct _MMCOLOR_TABLES { ULONG_PTR Flink; PVOID Blink; ULONG_PTR Count; } MMCOLOR_TABLES, *PMMCOLOR_TABLES; /* Free pool entry structure definition */ typedef struct _MMFREE_POOL_ENTRY { LIST_ENTRY List; PFN_COUNT Size; PMMFREE_POOL_ENTRY Owner; } MMFREE_POOL_ENTRY, *PMMFREE_POOL_ENTRY; /* Memory layout structure definition */ typedef struct _MMMEMORY_LAYOUT { PMMPFN PfnDatabase; PFN_NUMBER PfnDatabaseSize; PVOID SelfMapAddress; PVOID HardwarePoolStart; PVOID HardwarePoolEnd; PVOID HyperSpaceStart; PVOID HyperSpaceEnd; PVOID LoaderMappingsStart; PVOID LoaderMappingsEnd; PFN_NUMBER LoaderMappingsSize; PVOID NonCanonicalStart; PVOID NonCanonicalEnd; PVOID NonPagedPoolStart; PVOID NonPagedPoolEnd; PFN_NUMBER NonPagedPoolSize; PVOID NonPagedExpansionPoolStart; PVOID NonPagedExpansionPoolEnd; PFN_NUMBER NonPagedExpansionPoolSize; PVOID NonPagedSystemPoolStart; PVOID NonPagedSystemPoolEnd; PFN_NUMBER NonPagedSystemPoolSize; PVOID PagedPoolStart; PVOID PagedPoolEnd; PFN_NUMBER PagedPoolSize; PVOID ReservedSystemPoolStart; PVOID ReservedSystemPoolEnd; PVOID SessionSpaceStart; PVOID SessionSpaceEnd; PFN_NUMBER SessionSpaceSize; PVOID SharedSystemPageStart; PVOID SharedSystemPageEnd; PVOID SystemCacheStart; PVOID SystemCacheEnd; PVOID SystemWorkingSetStart; PVOID SystemWorkingSetEnd; PVOID UserSpaceStart; PVOID UserSpaceEnd; PVOID PteSpaceStart; PVOID PteSpaceEnd; } MMMEMORY_LAYOUT, *PMMMEMORY_LAYOUT; /* Page Frame Entry structure definition */ typedef struct _MMPFNENTRY { USHORT Modified:1; USHORT ReadInProgress:1; USHORT WriteInProgress:1; USHORT PrototypePte:1; USHORT PageColor:4; USHORT PageLocation:3; USHORT RemovalRequested:1; USHORT CacheAttribute:2; USHORT Rom:1; USHORT ParityError:1; } MMPFNENTRY, *PMMPFNENTRY; /* Page Frame List structure definition */ typedef struct _MMPFNLIST { PFN_NUMBER Total; MMPAGELISTS ListName; PFN_NUMBER Flink; PFN_NUMBER Blink; } MMPFNLIST, *PMMPFNLIST; /* Physical memory run structure definition */ typedef struct _PHYSICAL_MEMORY_RUN { PFN_NUMBER BasePage; PFN_NUMBER PageCount; } PHYSICAL_MEMORY_RUN, *PPHYSICAL_MEMORY_RUN; /* Physical memory descriptor structure definition */ typedef struct _PHYSICAL_MEMORY_DESCRIPTOR { ULONG NumberOfRuns; PFN_NUMBER NumberOfPages; PHYSICAL_MEMORY_RUN Run[1]; } PHYSICAL_MEMORY_DESCRIPTOR, *PPHYSICAL_MEMORY_DESCRIPTOR; /* Pool header structure definition */ typedef struct _POOL_HEADER { union { struct { USHORT PreviousSize:9; USHORT PoolIndex:7; USHORT BlockSize:9; USHORT PoolType:7; }; ULONG Long; }; union { ULONG PoolTag; PEPROCESS ProcessBilled; struct { USHORT AllocatorBackTraceIndex; USHORT PoolTagHash; }; }; } POOL_HEADER, *PPOOL_HEADER; /* Pool descriptor structure definition */ typedef struct _POOL_TRACKING_BIG_ALLOCATIONS { ULONG NumberOfPages; PVOID QuotaObject; ULONG Tag; PVOID VirtualAddress; } POOL_TRACKING_BIG_ALLOCATIONS, *PPOOL_TRACKING_BIG_ALLOCATIONS; /* Pool tracking table structure definition */ typedef struct _POOL_TRACKING_TABLE { LONG NonPagedAllocations; SIZE_T NonPagedBytes; LONG NonPagedFrees; LONG PagedAllocations; SIZE_T PagedBytes; LONG PagedFrees; ULONG Tag; } POOL_TRACKING_TABLE, *PPOOL_TRACKING_TABLE; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_MMTYPES_H */ ================================================ FILE: sdk/xtdk/potypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/potypes.h * DESCRIPTION: Power manager subsystem structures definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_POTYPES_H #define __XTDK_POTYPES_H #include #include #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Power Manager routine callbacks */ typedef VOID (XTFASTCALL *PPROCESSOR_IDLE_FUNCTION)(IN PPROCESSOR_POWER_STATE PowerState); typedef XTSTATUS (XTFASTCALL *PSET_PROCESSOR_THROTTLE)(IN UCHAR Throttle); /* Processor IDLE times structure definition */ typedef struct _PROCESSOR_IDLE_TIMES { ULONGLONG StartTime; ULONGLONG EndTime; ULONG IdleHandlerReserved[4]; } PROCESSOR_IDLE_TIMES, *PPROCESSOR_IDLE_TIMES; /* Processor performance state structure definition */ typedef struct _PROCESSOR_PERF_STATE { UCHAR PercentFrequency; UCHAR MinCapacity; USHORT Power; UCHAR IncreaseLevel; UCHAR DecreaseLevel; USHORT Flags; ULONG IncreaseTime; ULONG DecreaseTime; ULONG IncreaseCount; ULONG DecreaseCount; ULONGLONG PerformanceTime; } PROCESSOR_PERF_STATE, *PPROCESSOR_PERF_STATE; /* Processor power state structure definition */ typedef struct _PROCESSOR_POWER_STATE { PPROCESSOR_IDLE_FUNCTION IdleFunction; ULONG Idle0TimeLimit; ULONG Idle0LastTime; PVOID IdleHandlers; PVOID IdleState; ULONG IdleHandlersCount; ULONGLONG LastCheck; PROCESSOR_IDLE_TIMES IdleTimes; ULONG IdleTime1; ULONG PromotionCheck; ULONG IdleTime2; UCHAR CurrentThrottle; UCHAR ThermalThrottleLimit; UCHAR CurrentThrottleIndex; UCHAR ThermalThrottleIndex; ULONG PerfSystemTime; ULONG PerfIdleTime; ULONG LastSysTime; ULONGLONG TotalIdleStateTime[3]; ULONG TotalIdleTransitions[3]; ULONGLONG PreviousC3StateTime; UCHAR KneeThrottleIndex; UCHAR ThrottleLimitIndex; UCHAR PerfStatesCount; UCHAR ProcessorMinThrottle; UCHAR ProcessorMaxThrottle; UCHAR LastBusyPercentage; UCHAR LastC3Percentage; UCHAR LastAdjustedBusyPercentage; ULONG PromotionCount; ULONG DemotionCount; ULONG ErrorCount; ULONG RetryCount; ULONG Flags; LARGE_INTEGER PerfCounterFrequency; ULONG PerfTickCount; KTIMER PerfTimer; KDPC PerfDpc; PPROCESSOR_PERF_STATE PerfStates; PSET_PROCESSOR_THROTTLE PerfSetThrottle; ULONG LastC3UserTime; } PROCESSOR_POWER_STATE, *PPROCESSOR_POWER_STATE; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_POTYPES_H */ ================================================ FILE: sdk/xtdk/pstypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/pstypes.h * DESCRIPTION: Process-related data structure definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_PSTYPES_H #define __XTDK_PSTYPES_H #include #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Kernel's representation of a process object */ typedef struct _EPROCESS { KPROCESS ProcessControlBlock; UINT Reserved0; } EPROCESS, *PEPROCESS; /* Kernel's representation of a thread object */ typedef struct _ETHREAD { KTHREAD ThreadControlBlock; UINT Reserved0; } ETHREAD, *PETHREAD; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_PSTYPES_H */ ================================================ FILE: sdk/xtdk/rtlfuncs.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/rtlfuncs.h * DESCRIPTION: XT runtime library routines * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_RTLFUNCS_H #define __XTDK_RTLFUNCS_H #include #include #include #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Runtime Library routines forward references */ XTCLINK XTAPI VOID RtlClearAllBits(IN PRTL_BITMAP BitMap); XTCLINK XTAPI VOID RtlClearBit(IN PRTL_BITMAP BitMap, IN ULONG_PTR Bit); XTCLINK XTAPI VOID RtlClearBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR StartingIndex, IN ULONG_PTR Length); XTCLINK XTAPI ULONG RtlClearSetBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index); XTCLINK XTAPI BOOLEAN RtlCompareGuids(IN PGUID Guid1, IN PGUID Guid2); XTCLINK XTAPI SIZE_T RtlCompareMemory(IN PCVOID LeftBuffer, IN PCVOID RightBuffer, IN SIZE_T Length); XTCLINK XTAPI SIZE_T RtlCompareString(IN PCSTR String1, IN PCSTR String2, IN SIZE_T Length); XTCLINK XTAPI SIZE_T RtlCompareStringInsensitive(IN PCSTR String1, IN PCSTR String2, IN SIZE_T Length); XTCLINK XTAPI SIZE_T RtlCompareWideString(IN PCWSTR String1, IN PCWSTR String2, IN SIZE_T Length); XTCLINK XTAPI SIZE_T RtlCompareWideStringInsensitive(IN PCWSTR String1, IN PCWSTR String2, IN SIZE_T Length); XTCLINK XTAPI PCHAR RtlConcatenateString(OUT PCHAR Destination, IN PCHAR Source, IN SIZE_T Count); XTCLINK XTAPI PWCHAR RtlConcatenateWideString(OUT PWCHAR Destination, IN PWCHAR Source, IN SIZE_T Count); XTCLINK XTAPI LARGE_INTEGER RtlConvertToLargeInteger32(IN LONG Value); XTCLINK XTAPI LARGE_INTEGER RtlConvertToLargeIntegerUnsigned32(IN ULONG Value); XTCLINK XTAPI VOID RtlCopyMemory(OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length); XTCLINK XTAPI VOID RtlCopyString(IN PCHAR Destination, IN PCSTR Source, IN ULONG Length); XTCLINK XTAPI VOID RtlCopyWideString(IN PWCHAR Destination, IN PCWSTR Source, IN ULONG Length); XTCLINK XTAPI LARGE_INTEGER RtlDivideLargeInteger(IN LARGE_INTEGER Dividend, IN ULONG Divisor, OUT PULONG Remainder); XTCLINK XTAPI ULONG_PTR RtlFindClearBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index); XTCLINK XTAPI ULONG_PTR RtlFindSetBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index); XTCLINK XTAPI PCSTR RtlFindString(IN PCSTR Source, IN PCSTR Search); XTCLINK XTAPI PCSTR RtlFindStringInsensitive(IN PCSTR Source, IN PCSTR Search); XTCLINK XTAPI PCWSTR RtlFindWideString(IN PCWSTR Source, IN PCWSTR Search); XTCLINK XTAPI PCWSTR RtlFindWideStringInsensitive(IN PCWSTR Source, IN PCWSTR Search); XTCLINK XTAPI VOID RtlInitializeBitMap(IN PRTL_BITMAP BitMap, IN PULONG_PTR Buffer, IN ULONG Size); XTCLINK XTCDECL VOID RtlInitializeListHead(IN PLIST_ENTRY ListHead); XTCLINK XTCDECL VOID RtlInsertHeadList(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); XTCLINK XTCDECL VOID RtlInsertTailList(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); XTCLINK XTCDECL BOOLEAN RtlListEmpty(IN PLIST_ENTRY ListHead); XTCLINK XTCDECL BOOLEAN RtlListLoop(IN PLIST_ENTRY ListHead); XTCLINK XTAPI VOID RtlMoveMemory(OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length); XTCLINK XTAPI LARGE_INTEGER RtlMultiplyLargeInteger(IN LARGE_INTEGER Multiplicand, IN LONG Multiplier); XTCLINK XTCDECL VOID RtlRemoveEntryList(IN PLIST_ENTRY Entry); XTCLINK XTAPI VOID RtlReverseString(IN OUT PCHAR String, IN ULONG Length); XTCLINK XTAPI VOID RtlReverseWideString(IN OUT PWCHAR String, IN ULONG Length); XTCLINK XTAPI BOOLEAN RtlSameMemory(IN PCVOID LeftBuffer, IN PCVOID RightBuffer, IN SIZE_T Length); XTCLINK XTAPI VOID RtlSetAllBits(IN PRTL_BITMAP BitMap); XTCLINK XTAPI VOID RtlSetBit(IN PRTL_BITMAP BitMap, IN ULONG_PTR Bit); XTCLINK XTAPI VOID RtlSetBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR StartingIndex, IN ULONG_PTR Length); XTCLINK XTAPI ULONG RtlSetClearBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index); XTCLINK XTAPI VOID RtlSetMemory(OUT PVOID Destination, IN UCHAR Byte, IN SIZE_T Length); XTCLINK XTAPI SIZE_T RtlStringLength(IN PCSTR String, IN SIZE_T MaxLength); XTCLINK XTAPI SIZE_T RtlStringToWideString(OUT PWCHAR Destination, IN PCSTR *Source, IN SIZE_T Length); XTCLINK XTAPI BOOLEAN RtlTestBit(IN PRTL_BITMAP BitMap, IN ULONG_PTR Bit); XTCLINK XTAPI XTSTATUS RtlTimeFieldsToUnixEpoch(IN PTIME_FIELDS TimeFields, OUT PLONGLONG UnixTime); XTCLINK XTAPI XTSTATUS RtlTimeFieldsToXtEpoch(IN PTIME_FIELDS TimeFields, OUT PLARGE_INTEGER XtTime); XTCLINK XTAPI PCHAR RtlTokenizeString(IN PCHAR String, IN PCSTR Delimiter, IN OUT PCHAR *SavePtr); XTCLINK XTAPI PWCHAR RtlTokenizeWideString(IN PWCHAR String, IN PCWSTR Delimiter, IN OUT PWCHAR *SavePtr); XTCLINK XTAPI CHAR RtlToLowerCharacter(IN CHAR Character); XTCLINK XTAPI WCHAR RtlToLowerWideCharacter(IN WCHAR Character); XTCLINK XTAPI CHAR RtlToUpperCharacter(IN CHAR Character); XTCLINK XTAPI WCHAR RtlToUpperWideCharacter(IN WCHAR Character); XTCLINK XTAPI PCHAR RtlTrimLeftString(IN PCHAR String); XTCLINK XTAPI PWCHAR RtlTrimLeftWideString(IN PWCHAR String); XTCLINK XTAPI PCHAR RtlTrimRightString(IN PCHAR String); XTCLINK XTAPI PWCHAR RtlTrimRightWideString(IN PWCHAR String); XTCLINK XTAPI PCHAR RtlTrimString(IN PCHAR String); XTCLINK XTAPI PWCHAR RtlTrimWideString(IN PWCHAR String); XTCLINK XTAPI SIZE_T RtlWideStringLength(IN PCWSTR String, IN SIZE_T MaxLength); XTCLINK XTAPI VOID RtlZeroMemory(OUT PVOID Destination, IN SIZE_T Length); #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_RTLFUNCS_H */ ================================================ FILE: sdk/xtdk/rtltypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/rtltypes.h * DESCRIPTION: Runtime library structures definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_RTLTYPES_H #define __XTDK_RTLTYPES_H #include #include /* UUID string lengths */ #define GUID_STRING_LENGTH 38 #define PARTUUID_STRING_LENGTH 13 /* Maximum double/integer value string length */ #define MAX_DOUBLE_STRING_SIZE 15 #define MAX_INTEGER_STRING_SIZE 25 /* Floating point definitions */ #define DOUBLE_EXPONENT_MASK 0x7FF0000000000000ULL #define DOUBLE_EXPONENT_SHIFT 0x34 #define DOUBLE_EXPONENT_BIAS 0x3FF #define DOUBLE_HIGH_VALUE_MASK 0x000FFFFF #define DOUBLE_HIGH_VALUE_SHIFT 0x20 #define DOUBLE_PRECISION 6 #define DOUBLE_HEX_PRECISION 13 #define DOUBLE_SCIENTIFIC_PRECISION -4 #define DOUBLE_SIGN_BIT 0x8000000000000000ULL /* Print flag definitions */ #define PFL_ALWAYS_PRINT_SIGN 0x00000001 #define PFL_SPACE_FOR_PLUS 0x00000002 #define PFL_LEFT_JUSTIFIED 0x00000004 #define PFL_LEADING_ZEROES 0x00000008 #define PFL_LONG_INTEGER 0x00000010 #define PFL_LONG_DOUBLE 0x00000020 #define PFL_WIDE_CHARACTER 0x00000040 #define PFL_SHORT_VALUE 0x00000080 #define PFL_UNSIGNED 0x00000100 #define PFL_UPPERCASE 0x00000200 #define PFL_PRINT_RADIX 0x00000400 #define PFL_FLOAT_FORMAT 0x00000800 #define PFL_SCI_FORMAT 0x00001000 #define PFL_DIGIT_PRECISION 0x00002000 #define PFL_THOUSANDS_GROUPING 0x00004000 /* Cryptographic related definitions */ #define SHA1_BLOCK_SIZE 64 #define SHA1_DIGEST_SIZE 20 /* Time related definitions */ #define TIME_SECONDS_PER_MINUTE 60 #define TIME_SECONDS_PER_HOUR 3600 #define TIME_SECONDS_PER_DAY 86400 #define TIME_TICKS_PER_SECOND 10000000 #define TIME_TICKS_PER_MILLISECOND 10000 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Runtime Library routine callbacks */ typedef XTSTATUS (*PWRITE_CHARACTER)(IN CHAR Character); typedef XTSTATUS (*PWRITE_WIDE_CHARACTER)(IN WCHAR Character); /* Variable types enumeration list */ typedef enum _RTL_VARIABLE_TYPE { TypeUnknown, TypeAnsiString, TypeBoolean, TypeChar, TypeFloat, TypeGuid, TypeInteger, TypeString, TypeUnicodeString, TypeWideChar, TypeWideString } RTL_VARIABLE_TYPE, *PRTL_VARIABLE_TYPE; /* Bit Map structure definition */ typedef struct _RTL_BITMAP { ULONG Size; PULONG_PTR Buffer; } RTL_BITMAP, *PRTL_BITMAP; /* Runtime Library print context structure definition */ typedef struct _RTL_PRINT_CONTEXT { PWRITE_CHARACTER WriteCharacter; PWRITE_WIDE_CHARACTER WriteWideCharacter; ULONG CharactersWritten; } RTL_PRINT_CONTEXT, *PRTL_PRINT_CONTEXT; /* Runtime Library print format properties structure definition */ typedef struct _RTL_PRINT_FORMAT_PROPERTIES { RTL_VARIABLE_TYPE VariableType; ULONG Radix; LONG FieldWidth; LONG IntegerSize; LONG Precision; LONG Flags; } RTL_PRINT_FORMAT_PROPERTIES, *PRTL_PRINT_FORMAT_PROPERTIES; /* Runtime Library SHA-1 context structure definition */ typedef struct _RTL_SHA1_CONTEXT { ULONG State[5]; ULONG Count[2]; UCHAR Buffer[SHA1_BLOCK_SIZE]; } RTL_SHA1_CONTEXT, *PRTL_SHA1_CONTEXT; /* Runtime time fields structure definition */ typedef struct _TIME_FIELDS { SHORT Year; SHORT Month; SHORT Day; SHORT Hour; SHORT Minute; SHORT Second; SHORT Milliseconds; SHORT Weekday; } TIME_FIELDS, *PTIME_FIELDS; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_RTLTYPES_H */ ================================================ FILE: sdk/xtdk/xtbase.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtbase.h * DESCRIPTION: Basic and common native XT structures * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_XTBASE_H #define __XTDK_XTBASE_H #include #include #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Kernel affinity */ typedef ULONG_PTR KAFFINITY, *PKAFFINITY; /* Kernel priority */ typedef LONG KPRIORITY, *PKPRIORITY; /* Processor modes */ typedef CHAR KPROCESSOR_MODE, *PKPROCESSOR_MODE; /* Interrupt Request Run Level (IRQL) */ typedef UCHAR KRUNLEVEL, *PKRUNLEVEL; /* Spin locks synchronization mechanism */ typedef ULONG_PTR KSPIN_LOCK, *PKSPIN_LOCK; /* Page Frame Number count */ typedef ULONG PFN_COUNT; /* Page Frame Number */ typedef ULONG_PTR PFN_NUMBER, *PPFN_NUMBER; /* Physical address */ typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; /* 128-bit buffer containing a unique identifier value */ typedef struct _GUID { UINT Data1; USHORT Data2; USHORT Data3; UCHAR Data4[8]; } GUID, *PGUID; /* Double linked list structure definition */ typedef struct _LIST_ENTRY { PLIST_ENTRY Flink; PLIST_ENTRY Blink; } LIST_ENTRY, *PLIST_ENTRY; /* 32-bit double linked list structure definition */ typedef struct _LIST_ENTRY32 { ULONG Flink; ULONG Blink; } LIST_ENTRY32, *PLIST_ENTRY32; /* 64-bit double linked list structure definition */ typedef struct _LIST_ENTRY64 { ULONGLONG Flink; ULONGLONG Blink; } LIST_ENTRY64, *PLIST_ENTRY64; /* Single linked list structure definition */ typedef struct _SINGLE_LIST_ENTRY { PSINGLE_LIST_ENTRY Next; } SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY; /* Header for a sequenced single linked list union definition */ typedef union _SINGLE_LIST_HEADER { ULONGLONG Alignment; struct { SINGLE_LIST_ENTRY Next; USHORT Depth; USHORT Sequence; }; } SINGLE_LIST_HEADER, *PSINGLE_LIST_HEADER; /* 128-bit 16-byte aligned XMM register */ typedef struct _M128 { ULONGLONG Low; LONGLONG High; } ALIGN(16) M128, *PM128; /* Dispatcher object header structure definition */ typedef struct _DISPATCHER_HEADER { UCHAR Type; union { UCHAR Absolute; UCHAR NpxIrql; }; UCHAR Inserted; BOOLEAN DebugActive; LONG SignalState; LIST_ENTRY WaitListHead; } DISPATCHER_HEADER, *PDISPATCHER_HEADER; #endif /* __XTOS_ASSEMBLER_ */ #endif /* __XTDK_XTBASE_H */ ================================================ FILE: sdk/xtdk/xtblapi.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtblapi.h * DESCRIPTION: Top level header for the XT Boot Loader API * DEVELOPERS: Rafal Kupiec */ /* Base XT headers */ #include #include #include #include #include /* XT forward references */ #include /* Architecture-specific XT forward references */ #include ARCH_HEADER(xtstruct.h) /* Architecture-independent XT API */ #include #include #include #include #include #include /* Architecture independent XT kernel data types */ #include #include #include /* Architecture dependent XT kernel data types */ #include ARCH_HEADER(artypes.h) #include ARCH_HEADER(hltypes.h) #include ARCH_HEADER(ketypes.h) #include ARCH_HEADER(mmtypes.h) /* Boot Manager specific structures */ #include #include #include ================================================ FILE: sdk/xtdk/xtcompat.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtcompat.h * DESCRIPTION: C/C++ compatibility macros * DEVELOPERS: Aiken Harris */ #ifndef __XTDK_XTCOMPAT_H #define __XTDK_XTCOMPAT_H /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ #ifdef __cplusplus /* C++ definitions */ #define NULLPTR nullptr #define VIRTUAL virtual #define XTCLINK extern "C" #define XTSYMBOL(Name) __asm__(Name) /* C++ boolean type */ typedef bool BOOLEAN, *PBOOLEAN; #define TRUE true #define FALSE false /* C++ widechar type */ typedef wchar_t wchar; #else /* C definitions */ #define NULLPTR ((void *)0) #define VIRTUAL #define XTCLINK #define XTSYMBOL(Name) /* C boolean type */ typedef enum _BOOLEAN { FALSE = 0, TRUE = 1 } BOOLEAN, *PBOOLEAN; /* C widechar type */ typedef unsigned short wchar; #endif #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_XTCOMPAT_H */ ================================================ FILE: sdk/xtdk/xtdebug.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtdebug.h * DESCRIPTION: XT debugging support * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_XTDEBUG_H #define __XTDK_XTDEBUG_H /* Debugging macros */ #define CHECKPOINT DebugPrint(L"Checkpoint reached at %s:%d\n", __RELFILE__, __LINE__); #define DEPRECATED DebugPrint(L"Called deprecated routine '%s()' at %s:%d\n", \ __FUNCTION__, __RELFILE__, __LINE__); #define UNIMPLEMENTED DebugPrint(L"Called unimplemented routine '%s()' at %s:%d\n", \ __FUNCTION__, __RELFILE__, __LINE__); /* XTOS platform debugging macros */ #ifdef DBG #define DEBUG 1 #define DebugPrint(Format, ...) DbgPrint(Format, __VA_ARGS__); #else #define DEBUG 0 #define DebugPrint(Format, ...) ((VOID)NULLPTR) #endif #endif /* __XTDK_XTDEBUG_H */ ================================================ FILE: sdk/xtdk/xtdefs.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtdefs.h * DESCRIPTION: XT definitions for basic types * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_XTDEFS_H #define __XTDK_XTDEFS_H /* Routines and arguments modifiers */ #define IN #define OUT #define XTAPI __stdcall #define XTCDECL __cdecl #define XTFASTCALL __fastcall #define XTVECTORCALL __vectorcall #define XTINLINE __inline #define XTASSEMBLY __attribute__((naked)) #define XTINTERRUPT __attribute__((interrupt)) /* Variable modifiers */ #define CONST const #define EXTERN extern #define STRUCT struct #define STATIC static #define UNION union #define VOLATILE volatile /* Type limits */ #define MINCHAR 0x80 #define MAXCHAR 0x7F #define MINSHORT 0x8000 #define MAXSHORT 0x7FFF #define MINLONG 0x80000000 #define MAXLONG 0x7FFFFFFF #define MAXULONG 0xFFFFFFFF /* Pointer limits */ #define MININT_PTR (~MAXINT_PTR) #define MAXINT_PTR ((INT_PTR)(MAXUINT_PTR >> 1)) #define MAXUINT_PTR (~((UINT_PTR)0)) #define MINLONG_PTR (~MAXLONG_PTR) #define MAXLONG_PTR ((LONG_PTR)(MAXULONG_PTR >> 1)) #define MAXULONG_PTR (~((ULONG_PTR)0)) /* Number of bits per byte */ #define BITS_PER_BYTE 8 /* Preprocessor macros for defining an additional compiler attributes */ #define ALIGN(Alignment) __attribute__((aligned(Alignment))) #define PACKED __attribute__((packed)) #define SEGMENT(Segment) __attribute__((section(Segment))) #define USED __attribute__((__used__)) /* Macro for calculating size of an array */ #define ARRAY_SIZE(Array) (sizeof(Array) / sizeof(*Array)) /* Macros for converting Binary Coded Decimal (BCD) into decimal and vice versa */ #define BCD_TO_DECIMAL(Value) (((Value) & 0x0F) + (((Value) >> 4) * 10)) #define DECIMAL_TO_BCD(Value) ((((Value) / 10) << 4) | ((Value) % 10)) /* Macros for concatenating two strings */ #define CONCAT_STRING(Str1, Str2) Str1##Str2 #define CONCATENATE(Str1, Str2) CONCAT_STRING(Str1, Str2) /* Macro for accessing the base address of a structure from a structure member */ #define CONTAIN_RECORD(Address, Type, Field) ((Type *)((char *)(Address) - FIELD_OFFSET(Type, Field))) /* EFI size to pages conversion macro */ #define EFI_SIZE_TO_PAGES(Size) (((Size) >> EFI_PAGE_SHIFT) + (((Size) & EFI_PAGE_MASK) ? 1 : 0)) /* Macro for calculating byte offset of a field in the structure */ #define FIELD_OFFSET(Structure, Field) __builtin_offsetof(Structure, Field) /* Macro for calculating size of a field in the structure */ #define FIELD_SIZE(Structure, Field) (sizeof(((Structure *)0)->Field)) /* Macros for calculating minimum and maximum of two values */ #define MIN(A, B) (((A) < (B)) ? (A) : (B)) #define MAX(A, B) (((A) > (B)) ? (A) : (B)) /* Macro that page-aligns a virtual address */ #define PAGE_ALIGN(VirtualAddress) ((PVOID)((ULONG_PTR)VirtualAddress & ~MM_PAGE_MASK)) /* Macro that returns offset of the virtual address */ #define PAGE_OFFSET(VirtualAddress) ((ULONG)((ULONG_PTR)VirtualAddress & MM_PAGE_MASK)) /* Macros for bitwise rotating */ #define ROTATE_LEFT(Value, Count) ((Value << Count) | (Value >> (32 - Count))) #define ROTATE_RIGHT(Value, Count) ((Value >> Count) | (Value << (32 - Count))) /* Macro for rounding down */ #define ROUND_DOWN(Value, Alignment) ((Value) & ~((Alignment) - 1)) /* Macro for rounding up */ #define ROUND_UP(Value, Alignment) ROUND_DOWN((Value) + (Alignment - 1), Alignment) /* Macros for defining signatures built from ASCII characters */ #define SIGNATURE16(A, B) ((A) | (B << 8)) #define SIGNATURE32(A, B, C, D) (SIGNATURE16(A, B) | (SIGNATURE16(C, D) << 16)) #define SIGNATURE64(A, B, C, D, E, F, G, H) (SIGNATURE32(A, B, C, D) | ((UINT64)(SIGNATURE32(E, F, G, H)) << 32)) /* XT size <-> pages conversion macro */ #define PAGES_TO_SIZE(Pages) ((Pages) << MM_PAGE_SHIFT) #define SIZE_TO_PAGES(Size) (((Size) >> MM_PAGE_SHIFT) + (((Size) & (MM_PAGE_MASK)) ? 1 : 0)) /* Macros for concatenating strings */ #define STRINGIFY(String...) STRINGIZE(String) #define STRINGIZE(String...) #String /* Macro for generating unique identifiers */ #define UNIQUE(Prefix) CONCATENATE(CONCATENATE(__UNIQUE_ID_, Prefix), __COUNTER__) /* Variadic ABI functions */ #define VA_ARG(Marker, Type) ((sizeof(Type) < sizeof(UINT_PTR)) ? \ (Type)(__builtin_va_arg(Marker, UINT_PTR)) : \ (Type)(__builtin_va_arg(Marker, Type))) #define VA_COPY(Dest, Start) __builtin_va_copy(Dest, Start) #define VA_START(Marker, Parameter) __builtin_va_start(Marker, Parameter) #define VA_END(Marker) __builtin_va_end(Marker) /* Data conversion macros */ #define HandleToLong(Var) ((LONG)(LONG_PTR)Var) #define HandleToUlong(Var) ((ULONG)(ULONG_PTR)Var) #define IntToPtr(Var) ((PVOID)(INT_PTR)Var) #define LongToHandle(Var) ((HANDLE)(LONG_PTR)Var) #define LongToPtr(Var) ((PVOID)(LONG_PTR)Var) #define PtrToInt(Var) ((INT)(INT_PTR)Var) #define PtrToLong(Var) ((LONG)(LONG_PTR)Var) #define PtrToShort(Var) ((SHORT)(LONG_PTR)Var) #define PtrToUint(Var) ((UINT)(UINT_PTR)Var) #define PtrToUlong(Var) ((ULONG)(ULONG_PTR)Var) #define PtrToUshort(Var) ((USHORT)(ULONG_PTR)Var) #define UintToPtr(Var) ((PVOID)(UINT_PTR)Var) #define UlongToHandle(Var) ((HANDLE)(ULONG_PTR)Var) #define UlongToPtr(Var) ((PVOID)(ULONG_PTR)Var) #endif /* __XTDK_XTDEFS_H */ ================================================ FILE: sdk/xtdk/xtfont.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtfont.h * DESCRIPTION: XT framebuffer native font * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_XTFONT_H #define __XTDK_XTFONT_H #include #include /* C/C++ specific code */ #ifndef D__XTOS_ASSEMBLER__ /* SSF2 font header */ typedef struct _SSFN_FONT_HEADER { UCHAR Magic[4]; UINT Size; UCHAR Type; UCHAR Features; UCHAR Width; UCHAR Height; UCHAR Baseline; UCHAR Underline; USHORT FragmentsOffset; UINT CharactersOffset; UINT LigatureOffset; UINT KerningOffset; UINT ColorMapOffset; } SSFN_FONT_HEADER, *PSSFN_FONT_HEADER; /* XTOS font (VGA Unicode by Dmitry Yu. Bolkhovityanov (C) 2000, https://www.inp.nsk.su/~bolkhov/files/fonts/univga/) */ UCHAR XtFbDefaultFont[] = {0x78, 0x74, 0x66, 0x6E, 0x3B, 0xE7, 0x00, 0x00, 0x03, 0x00, 0x08, 0x10, 0x0C, 0x0D, 0x7D, 0x00, 0x41, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x67, 0x61, 0x20, 0x55, 0x6E, 0x69, 0x63, 0x6F, 0x64, 0x65, 0x00, 0x56, 0x47, 0x41, 0x00, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x00, 0x00, 0x42, 0x6F, 0x6C, 0x6B, 0x68, 0x6F, 0x76, 0x00, 0x43, 0x6F, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x30, 0x20, 0x44, 0x6D, 0x69, 0x74, 0x72, 0x79, 0x20, 0x42, 0x6F, 0x6C, 0x6B, 0x68, 0x6F, 0x76, 0x69, 0x74, 0x79, 0x61, 0x6E, 0x6F, 0x76, 0x2C, 0x20, 0x62, 0x6F, 0x6C, 0x6B, 0x68, 0x6F, 0x76, 0x40, 0x69, 0x6E, 0x70, 0x2E, 0x6E, 0x73, 0x6B, 0x2E, 0x73, 0x75, 0x00, 0x80, 0x00, 0x10, 0x80, 0x00, 0x7F, 0x80, 0x01, 0x18, 0x18, 0x80, 0x00, 0x28, 0x80, 0x00, 0x3E, 0x80, 0x01, 0x0C, 0x0C, 0x80, 0x01, 0x30, 0x18, 0x80, 0x01, 0x36, 0x36, 0x80, 0x01, 0x6E, 0x3B, 0x80, 0x06, 0x1E, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x06, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x00, 0x08, 0x80, 0x00, 0x7E, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x20, 0x80, 0x06, 0x3E, 0x63, 0x7F, 0x03, 0x03, 0x63, 0x3E, 0x80, 0x01, 0x36, 0x1C, 0x80, 0x06, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x00, 0x50, 0x80, 0x01, 0x06, 0x0C, 0x80, 0x02, 0x18, 0x18, 0x0C, 0x80, 0x06, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x01, 0x66, 0x66, 0x80, 0x03, 0x02, 0x81, 0x81, 0x7E, 0x80, 0x02, 0x10, 0x10, 0xEF, 0x80, 0x09, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x30, 0x1F, 0x80, 0x00, 0x18, 0x80, 0x02, 0x08, 0x1C, 0x36, 0x80, 0x03, 0x10, 0x20, 0x20, 0x1F, 0x80, 0x02, 0x36, 0x1C, 0x08, 0x80, 0x01, 0x33, 0x66, 0x80, 0x04, 0x10, 0x20, 0x40, 0x42, 0x3C, 0x80, 0x05, 0x20, 0x40, 0x40, 0x20, 0x18, 0x06, 0x80, 0x06, 0x30, 0x48, 0x70, 0x40, 0x20, 0x18, 0x06, 0x80, 0x03, 0x08, 0x38, 0x28, 0x1C, 0x80, 0x01, 0x77, 0x77, 0x80, 0x08, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x80, 0x08, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x66, 0x7F, 0x80, 0x04, 0x36, 0x51, 0x32, 0x14, 0x13, 0x80, 0x01, 0x7F, 0x7F, 0x80, 0x08, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x08, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x06, 0x3B, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x80, 0x06, 0x3B, 0x6E, 0x66, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x06, 0x3E, 0x63, 0x06, 0x1C, 0x30, 0x63, 0x3E, 0x80, 0x00, 0x36, 0x80, 0x06, 0x6E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x04, 0x60, 0x92, 0xA1, 0xC1, 0x7E, 0x80, 0x09, 0x6E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x33, 0x1E, 0x80, 0x08, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x01, 0x1C, 0x36, 0x80, 0x03, 0x02, 0x01, 0x81, 0x7E, 0x80, 0x06, 0x3E, 0x63, 0x03, 0x03, 0x03, 0x63, 0x3E, 0x80, 0x06, 0x63, 0x63, 0x6B, 0x6B, 0x6B, 0x7F, 0x36, 0x80, 0x00, 0x3C, 0x80, 0x02, 0x1C, 0x36, 0x1C, 0x80, 0x01, 0x66, 0x33, 0x80, 0x05, 0x82, 0x81, 0x81, 0x81, 0x42, 0x3C, 0x80, 0x06, 0xE0, 0x10, 0x11, 0x61, 0x81, 0x81, 0x7E, 0x80, 0x00, 0x3F, 0x80, 0x09, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x67, 0x66, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x66, 0x67, 0x80, 0x06, 0x7F, 0x33, 0x18, 0x0C, 0x06, 0x63, 0x7F, 0x80, 0x01, 0x0C, 0x18, 0x80, 0x08, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x01, 0xC0, 0xC0, 0x80, 0x02, 0x18, 0x18, 0x18, 0x80, 0x06, 0x60, 0x90, 0x8C, 0x79, 0x11, 0x11, 0x0E, 0x80, 0x03, 0x1C, 0xE2, 0x18, 0x07, 0x80, 0x03, 0x0E, 0xF1, 0x4C, 0x83, 0x80, 0x06, 0x30, 0x48, 0xF0, 0x40, 0x20, 0x18, 0x06, 0x80, 0x09, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x01, 0x60, 0x60, 0x80, 0x07, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x00, 0x14, 0x80, 0x08, 0x0E, 0xF1, 0x0C, 0x02, 0x01, 0x01, 0x01, 0x82, 0x7C, 0x80, 0x05, 0x80, 0xA8, 0x11, 0x21, 0x21, 0x1E, 0x80, 0x01, 0x28, 0x10, 0x80, 0x04, 0x70, 0x1C, 0x07, 0x1C, 0x70, 0x80, 0x04, 0x07, 0x1C, 0x70, 0x1C, 0x07, 0x80, 0x09, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x80, 0x09, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3F, 0x80, 0x09, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x46, 0x66, 0x7F, 0x80, 0x09, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x80, 0x09, 0x0F, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x80, 0x09, 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x63, 0x80, 0x09, 0x63, 0x67, 0x6F, 0x7F, 0x7B, 0x73, 0x63, 0x63, 0x63, 0x63, 0x80, 0x09, 0x38, 0x30, 0x30, 0x3C, 0x36, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x09, 0x70, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x3C, 0x80, 0x09, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x06, 0x37, 0x7F, 0x6B, 0x6B, 0x6B, 0x6B, 0x63, 0x80, 0x06, 0x63, 0x36, 0x1C, 0x1C, 0x1C, 0x36, 0x63, 0x80, 0x01, 0x18, 0x0C, 0x80, 0x08, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x66, 0x67, 0x80, 0x06, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x70, 0x80, 0x06, 0x33, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x06, 0x63, 0x73, 0x7B, 0x7F, 0x6F, 0x67, 0x63, 0x80, 0x01, 0x03, 0x03, 0x80, 0x04, 0x18, 0x24, 0x44, 0x44, 0x38, 0x80, 0x09, 0x0E, 0x01, 0x31, 0x0E, 0x02, 0x01, 0x01, 0x01, 0x82, 0x7C, 0x80, 0x00, 0x02, 0x80, 0x03, 0x08, 0x08, 0x08, 0x08, 0x80, 0x08, 0x20, 0x90, 0x48, 0x20, 0x10, 0x22, 0x41, 0x41, 0x3E, 0x80, 0x02, 0x1C, 0x30, 0x18, 0x80, 0x04, 0x10, 0x10, 0x20, 0x62, 0x9C, 0x80, 0x04, 0xE0, 0x11, 0xE1, 0x81, 0x7E, 0x80, 0x04, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x80, 0x09, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x66, 0x66, 0x67, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x06, 0x1C, 0x30, 0x60, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x63, 0x63, 0x36, 0x3E, 0x1C, 0x1C, 0x3E, 0x36, 0x63, 0x63, 0x80, 0x09, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x7F, 0x63, 0x61, 0x30, 0x18, 0x0C, 0x06, 0x43, 0x63, 0x7F, 0x80, 0x02, 0x0C, 0x0C, 0x18, 0x80, 0x09, 0x07, 0x06, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x67, 0x80, 0x09, 0x07, 0x06, 0x06, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x67, 0x80, 0x09, 0x3B, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x80, 0x09, 0x08, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x80, 0x06, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x80, 0x03, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0x63, 0x67, 0x6F, 0x7F, 0x7B, 0x73, 0x63, 0x63, 0x63, 0x80, 0x06, 0x33, 0x6E, 0x6C, 0x7E, 0x1B, 0x1B, 0x76, 0x80, 0x08, 0x3C, 0x66, 0x43, 0x03, 0x7B, 0x63, 0x63, 0x66, 0x5C, 0x80, 0x06, 0x67, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x67, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x00, 0x33, 0x80, 0x06, 0x3E, 0x63, 0x60, 0x60, 0x7F, 0x63, 0x3E, 0x80, 0x07, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x06, 0x3E, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x3E, 0x80, 0x08, 0x63, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x63, 0x3E, 0x80, 0x00, 0x04, 0x80, 0x08, 0x60, 0x90, 0x90, 0xE2, 0x81, 0x81, 0x81, 0x42, 0x3C, 0x80, 0x06, 0x98, 0x84, 0x98, 0x84, 0x80, 0x81, 0x7E, 0x80, 0x03, 0x30, 0x0C, 0x30, 0x0C, 0x80, 0x01, 0x30, 0x0C, 0x80, 0x01, 0x30, 0xC8, 0x80, 0x08, 0x63, 0x63, 0x63, 0x6B, 0x6B, 0x6B, 0x7F, 0x77, 0x36, 0x80, 0x03, 0x70, 0xC8, 0x5C, 0x36, 0x80, 0x07, 0x63, 0x63, 0x36, 0x36, 0x1C, 0x1C, 0x08, 0x08, 0x80, 0x02, 0x38, 0x38, 0x38, 0x80, 0x04, 0x30, 0x48, 0x50, 0x60, 0x3F, 0x80, 0x04, 0x30, 0x48, 0x48, 0x30, 0xCF, 0x80, 0x04, 0x20, 0xE0, 0x20, 0x18, 0x06, 0x80, 0x03, 0x60, 0x94, 0x8C, 0x7B, 0x80, 0x03, 0x18, 0x18, 0x18, 0x0C, 0x80, 0x09, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3C, 0x80, 0x09, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x09, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x08, 0x80, 0x09, 0x07, 0x06, 0x06, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x80, 0x04, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x09, 0x1F, 0x36, 0x66, 0x66, 0x6F, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x80, 0x09, 0x3E, 0x63, 0x03, 0x03, 0x03, 0x63, 0x3E, 0x18, 0x30, 0x1C, 0x80, 0x01, 0x33, 0x33, 0x80, 0x02, 0x18, 0x0C, 0x0C, 0x80, 0x08, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x80, 0x08, 0x3E, 0x63, 0x63, 0x06, 0x1C, 0x30, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x3B, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x80, 0x09, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x80, 0x00, 0x0C, 0x80, 0x09, 0x7F, 0x60, 0x30, 0x18, 0x3C, 0x60, 0x60, 0x60, 0x63, 0x3E, 0x80, 0x06, 0x3E, 0x63, 0x03, 0x1E, 0x03, 0x63, 0x3E, 0x80, 0x06, 0x3E, 0x63, 0x60, 0x3C, 0x60, 0x63, 0x3E, 0x80, 0x06, 0x36, 0x63, 0x6B, 0x6B, 0x6B, 0x6B, 0x36, 0x80, 0x08, 0x63, 0x63, 0x73, 0x7B, 0x7F, 0x6F, 0x67, 0x63, 0x63, 0x80, 0x06, 0x6B, 0x6B, 0x6B, 0x3E, 0x6B, 0x6B, 0x6B, 0x80, 0x06, 0x36, 0x63, 0x6B, 0x6B, 0x6B, 0x7F, 0x36, 0x80, 0x01, 0x18, 0x66, 0x80, 0x00, 0x66, 0x80, 0x01, 0x06, 0x06, 0x80, 0x04, 0x18, 0x24, 0x04, 0x78, 0x04, 0x80, 0x05, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x80, 0x03, 0x18, 0x04, 0x38, 0x04, 0x80, 0x09, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x41, 0x41, 0x21, 0x1E, 0x80, 0x00, 0x24, 0x80, 0x02, 0x60, 0x94, 0x7A, 0x80, 0x05, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x80, 0x08, 0x0E, 0xF1, 0x0C, 0x02, 0x29, 0x01, 0x11, 0x82, 0x7C, 0x80, 0x08, 0x04, 0x1C, 0x14, 0x0E, 0x10, 0x20, 0x40, 0x42, 0x3C, 0x80, 0x00, 0x40, 0x80, 0x03, 0x10, 0x10, 0x10, 0x10, 0x80, 0x01, 0x10, 0x28, 0x80, 0x06, 0xE0, 0x10, 0x11, 0x61, 0x81, 0x41, 0x3E, 0x80, 0x03, 0x18, 0x3C, 0x3C, 0x18, 0x80, 0x06, 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x80, 0x04, 0x57, 0x54, 0x72, 0x71, 0x77, 0x80, 0x01, 0xDB, 0xDB, 0x80, 0x06, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x07, 0x08, 0x08, 0x1C, 0x1C, 0x36, 0x36, 0x63, 0x63, 0x80, 0x01, 0x3B, 0x6E, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x04, 0x60, 0x92, 0x91, 0x61, 0xBE, 0x80, 0x03, 0x38, 0x04, 0x38, 0x04, 0x80, 0x06, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x80, 0x09, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x7B, 0x63, 0x63, 0x66, 0x5C, 0x80, 0x09, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x09, 0x63, 0x63, 0x63, 0x63, 0x6B, 0x6B, 0x6B, 0x7F, 0x77, 0x36, 0x80, 0x03, 0x08, 0x1C, 0x36, 0x63, 0x80, 0x06, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x63, 0x7F, 0x80, 0x03, 0x1C, 0x36, 0x36, 0x1C, 0x80, 0x05, 0x0E, 0x1B, 0x0C, 0x06, 0x13, 0x1F, 0x80, 0x05, 0x0E, 0x1B, 0x0C, 0x18, 0x1B, 0x0E, 0x80, 0x09, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6F, 0x03, 0x03, 0x03, 0x80, 0x05, 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x80, 0x0B, 0x08, 0x1C, 0x36, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x80, 0x09, 0x7C, 0x36, 0x33, 0x33, 0x7F, 0x33, 0x33, 0x33, 0x33, 0x73, 0x80, 0x0C, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3C, 0x18, 0x30, 0x1C, 0x80, 0x0B, 0x08, 0x1C, 0x22, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x66, 0x7F, 0x80, 0x0B, 0x08, 0x1C, 0x22, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x06, 0x5E, 0x23, 0x73, 0x6B, 0x67, 0x62, 0x3D, 0x80, 0x08, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3C, 0x80, 0x09, 0x30, 0x7C, 0x30, 0x3C, 0x36, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x09, 0x06, 0x1F, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x67, 0x80, 0x01, 0x66, 0x3C, 0x80, 0x08, 0x0F, 0x06, 0x06, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x80, 0x08, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x00, 0x1E, 0x80, 0x08, 0x7F, 0x63, 0x31, 0x18, 0x0C, 0x06, 0x43, 0x63, 0x7F, 0x80, 0x09, 0x1E, 0x33, 0x61, 0x60, 0x60, 0x60, 0x60, 0x61, 0x33, 0x1E, 0x80, 0x09, 0x3E, 0x63, 0x60, 0x60, 0x60, 0x7F, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x3E, 0x63, 0x43, 0x03, 0x1E, 0x03, 0x03, 0x43, 0x63, 0x3E, 0x80, 0x0B, 0xC0, 0xC0, 0x5E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x09, 0xC0, 0xC0, 0x60, 0x1E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x09, 0x7F, 0x63, 0x46, 0x0C, 0x18, 0x18, 0x0C, 0x46, 0x63, 0x7F, 0x80, 0x0B, 0xC0, 0xC0, 0x73, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x09, 0xC0, 0xC0, 0x60, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x09, 0x77, 0x36, 0x36, 0x36, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0x7C, 0x36, 0x33, 0x33, 0x7F, 0x33, 0x33, 0x33, 0x73, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x0C, 0x06, 0x1C, 0x80, 0x09, 0x1C, 0x18, 0x18, 0xFE, 0x9B, 0x5B, 0x5B, 0x5B, 0x3B, 0xF6, 0x80, 0x01, 0x3C, 0x66, 0x80, 0x09, 0x3E, 0x63, 0x7F, 0x03, 0x03, 0x63, 0x3E, 0x18, 0x30, 0x1C, 0x80, 0x09, 0x4E, 0x39, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x63, 0x62, 0x36, 0x34, 0x34, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0C, 0x08, 0x08, 0x08, 0x3E, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3E, 0x08, 0x08, 0x08, 0x80, 0x06, 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x80, 0x06, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x80, 0x03, 0x7F, 0x63, 0x63, 0x63, 0x80, 0x02, 0x18, 0x0C, 0x06, 0x80, 0x02, 0x18, 0x30, 0x18, 0x80, 0x02, 0x0E, 0x18, 0x0C, 0x80, 0x09, 0x7F, 0x66, 0x46, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x09, 0x08, 0x08, 0x1C, 0x1C, 0x36, 0x36, 0x63, 0x63, 0x63, 0x7F, 0x80, 0x09, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x80, 0x09, 0x08, 0x3E, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3E, 0x08, 0x08, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x36, 0x36, 0x77, 0x80, 0x08, 0x67, 0x66, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x66, 0x67, 0x80, 0x06, 0x7F, 0x66, 0x46, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x06, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x60, 0x80, 0x06, 0xC3, 0xC3, 0xC3, 0xCF, 0xDB, 0xDB, 0xCF, 0x80, 0x06, 0x3E, 0x63, 0x60, 0x7C, 0x60, 0x63, 0x3E, 0x80, 0x06, 0x43, 0x63, 0x26, 0x36, 0x1C, 0x1C, 0x08, 0x80, 0x02, 0x20, 0x3E, 0x02, 0x80, 0x01, 0x3E, 0x2A, 0x80, 0x01, 0x66, 0x18, 0x80, 0x0B, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0xE3, 0xC0, 0x80, 0x80, 0x08, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0xE3, 0xC0, 0x80, 0x80, 0x02, 0x30, 0x30, 0x3C, 0x80, 0x02, 0x18, 0x0C, 0x18, 0x80, 0x07, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0x40, 0x3C, 0x02, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x80, 0x08, 0x18, 0x04, 0x38, 0x04, 0x10, 0x10, 0x10, 0x10, 0x10, 0x80, 0x0A, 0x38, 0x04, 0x38, 0x04, 0x30, 0x48, 0x70, 0x40, 0x20, 0x18, 0x06, 0x80, 0x04, 0x28, 0x02, 0x81, 0x81, 0x7E, 0x80, 0x08, 0x0E, 0xF1, 0x0C, 0x02, 0x01, 0x11, 0x01, 0x82, 0x7C, 0x80, 0x06, 0x04, 0x04, 0x04, 0x34, 0x4C, 0x45, 0x3E, 0x80, 0x06, 0x24, 0x04, 0x04, 0x34, 0x4C, 0x45, 0x3E, 0x80, 0x09, 0x30, 0x48, 0x48, 0x3C, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x80, 0x05, 0x02, 0x0C, 0x72, 0x92, 0x9C, 0x67, 0x80, 0x04, 0x30, 0x48, 0x53, 0x34, 0x0E, 0x80, 0x04, 0x10, 0x28, 0x30, 0x10, 0x08, 0x80, 0x03, 0x50, 0x54, 0x34, 0x08, 0x80, 0x02, 0x18, 0x24, 0x18, 0x80, 0x03, 0x30, 0x08, 0x30, 0x08, 0x80, 0x08, 0x04, 0x0E, 0x0E, 0x1C, 0x18, 0x18, 0x10, 0x10, 0x10, 0x80, 0x08, 0x22, 0x3F, 0x1F, 0x06, 0x0C, 0x0C, 0x08, 0x08, 0x08, 0x80, 0x08, 0x52, 0x7F, 0x2F, 0x06, 0x0C, 0x0C, 0x08, 0x08, 0x08, 0x80, 0x08, 0x41, 0x63, 0x63, 0x36, 0x14, 0x1C, 0x08, 0x08, 0x08, 0x80, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x14, 0x36, 0x63, 0x63, 0x41, 0x80, 0x08, 0x0E, 0x1F, 0x11, 0x1F, 0x1E, 0x10, 0x30, 0x70, 0x60, 0x80, 0x07, 0x08, 0x08, 0x1C, 0x7F, 0x3E, 0x1C, 0x36, 0x22, 0x80, 0x04, 0x20, 0x20, 0x20, 0x20, 0x20, 0x80, 0x02, 0x60, 0x14, 0x7A, 0x80, 0x03, 0xC0, 0x20, 0xC0, 0x20, 0x80, 0x0B, 0xC4, 0x2A, 0xCC, 0x24, 0x02, 0x30, 0x48, 0x70, 0x40, 0x20, 0x18, 0x06, 0x80, 0x08, 0x0E, 0xF1, 0x0C, 0x02, 0x01, 0x29, 0x01, 0x82, 0x7C, 0x80, 0x08, 0x0E, 0xF1, 0x0C, 0x02, 0x11, 0x01, 0x11, 0x82, 0x7C, 0x80, 0x08, 0x0E, 0xF1, 0x0C, 0x02, 0x29, 0x01, 0x29, 0x82, 0x7C, 0x80, 0x05, 0x80, 0xA8, 0x11, 0x11, 0x09, 0xA6, 0x80, 0x00, 0x0A, 0x80, 0x07, 0x80, 0x40, 0x20, 0x10, 0x22, 0x41, 0x41, 0x3E, 0x80, 0x06, 0x94, 0x80, 0x98, 0x84, 0x98, 0x85, 0x7E, 0x80, 0x08, 0x25, 0x90, 0x48, 0x20, 0x10, 0x22, 0x41, 0x41, 0x3E, 0x80, 0x08, 0x1C, 0x02, 0x1C, 0x02, 0x18, 0x24, 0x44, 0x44, 0x38, 0x80, 0x06, 0x30, 0x48, 0x70, 0x40, 0x3C, 0x18, 0x06, 0x80, 0x0B, 0x08, 0x14, 0x18, 0x08, 0x04, 0x30, 0x48, 0x70, 0x40, 0x20, 0x18, 0x06, 0x80, 0x04, 0x10, 0x28, 0x06, 0x01, 0x7F, 0x80, 0x03, 0xA8, 0x51, 0x09, 0x06, 0x80, 0x04, 0x30, 0x30, 0x08, 0x08, 0x08, 0x80, 0x03, 0x08, 0x0C, 0x02, 0x7C, 0x80, 0x04, 0x10, 0x28, 0x44, 0x28, 0x10, 0x80, 0x08, 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x80, 0x03, 0x30, 0x18, 0x6E, 0x3B, 0x80, 0x08, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x08, 0x63, 0x63, 0x36, 0x3E, 0x1C, 0x3E, 0x36, 0x63, 0x63, 0x80, 0x03, 0xC0, 0x64, 0x0E, 0x1B, 0x80, 0x03, 0x03, 0x26, 0x70, 0xD8, 0x80, 0x03, 0x66, 0x66, 0x66, 0x33, 0x80, 0x09, 0x18, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x80, 0x06, 0x49, 0x22, 0x14, 0x49, 0x14, 0x22, 0x49, 0x80, 0x05, 0x0E, 0x1B, 0x1B, 0x1B, 0x1B, 0x0E, 0x80, 0x05, 0x18, 0x1C, 0x1E, 0x1B, 0x3F, 0x18, 0x80, 0x05, 0x1F, 0x03, 0x0F, 0x18, 0x1B, 0x0E, 0x80, 0x05, 0x1E, 0x03, 0x0F, 0x1B, 0x1B, 0x0E, 0x80, 0x05, 0x1F, 0x1B, 0x0C, 0x0C, 0x06, 0x06, 0x80, 0x05, 0x0E, 0x1B, 0x0E, 0x1B, 0x1B, 0x0E, 0x80, 0x05, 0x0E, 0x1B, 0x1B, 0x1E, 0x18, 0x0F, 0x80, 0x04, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x80, 0x05, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x80, 0x05, 0x06, 0x0C, 0x0C, 0x0C, 0x0C, 0x06, 0x80, 0x04, 0x0D, 0x1B, 0x1B, 0x1B, 0x1B, 0x80, 0x01, 0xA0, 0xA0, 0x80, 0x06, 0x0F, 0x07, 0x0D, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x02, 0x0C, 0x06, 0xFF, 0x80, 0x02, 0xFF, 0x06, 0x0C, 0x80, 0x02, 0x30, 0x60, 0xFF, 0x80, 0x02, 0xFF, 0x60, 0x30, 0x80, 0x04, 0x0C, 0x06, 0x7F, 0x06, 0x0C, 0x80, 0x04, 0x18, 0x30, 0x7F, 0x30, 0x18, 0x80, 0x03, 0x18, 0x24, 0x24, 0x18, 0x80, 0x06, 0x40, 0x60, 0x38, 0x0F, 0x38, 0x60, 0x40, 0x80, 0x06, 0x01, 0x03, 0x0E, 0x78, 0x0E, 0x03, 0x01, 0x80, 0x05, 0x7E, 0x03, 0x03, 0x03, 0x03, 0x7E, 0x80, 0x05, 0x3F, 0x60, 0x60, 0x60, 0x60, 0x3F, 0x80, 0x05, 0x7F, 0x03, 0x03, 0x03, 0x03, 0x7F, 0x80, 0x05, 0x7F, 0x60, 0x60, 0x60, 0x60, 0x7F, 0x80, 0x06, 0x60, 0x78, 0x6E, 0x63, 0x6E, 0x78, 0x60, 0x80, 0x06, 0x03, 0x0F, 0x3B, 0x63, 0x3B, 0x0F, 0x03, 0x80, 0x01, 0x08, 0x08, 0x80, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x80, 0x0F, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x80, 0x01, 0xFF, 0xC3, 0x80, 0x01, 0xC3, 0xFF, 0x80, 0x0F, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x80, 0x03, 0x38, 0x38, 0x38, 0x38, 0x80, 0x06, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x07, 0xEF, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x80, 0x06, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0xEF, 0x80, 0x08, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x02, 0x54, 0x7E, 0x55, 0x80, 0x05, 0x20, 0x20, 0x20, 0x20, 0x20, 0xC0, 0x80, 0x06, 0x60, 0x18, 0x04, 0x08, 0x10, 0x10, 0x0F, 0x80, 0x06, 0x60, 0x18, 0x04, 0x04, 0x08, 0x10, 0xEF, 0x80, 0x08, 0x20, 0x90, 0x48, 0x20, 0x10, 0x12, 0x21, 0x41, 0xBE, 0x80, 0x08, 0x30, 0x0C, 0x62, 0x18, 0x04, 0x08, 0x10, 0x10, 0x0F, 0x80, 0x08, 0x30, 0x0C, 0x62, 0x18, 0x04, 0x04, 0x08, 0x10, 0xEF, 0x80, 0x05, 0x80, 0x82, 0x81, 0x81, 0x42, 0x3C, 0x80, 0x06, 0x08, 0x1C, 0x32, 0x4A, 0x4C, 0xBC, 0x02, 0x80, 0x03, 0xE0, 0x18, 0x04, 0xFC, 0x80, 0x01, 0x10, 0x08, 0x80, 0x02, 0x60, 0x18, 0x06, 0x80, 0x03, 0x30, 0x08, 0x70, 0x08, 0x80, 0x05, 0x08, 0x08, 0x16, 0x11, 0x2E, 0xC0, 0x80, 0x08, 0x0E, 0xF1, 0x4C, 0x82, 0x01, 0x01, 0x01, 0x02, 0x7C, 0x80, 0x02, 0x80, 0xA8, 0x57, 0x80, 0x01, 0x54, 0xAB, 0x80, 0x09, 0x78, 0x44, 0x38, 0x44, 0x82, 0x01, 0x01, 0x01, 0x82, 0x7C, 0x80, 0x03, 0x70, 0x08, 0x08, 0x7F, 0x80, 0x03, 0x78, 0x44, 0x38, 0xC7, 0x80, 0x07, 0x42, 0x44, 0x48, 0x50, 0x20, 0x30, 0x48, 0x3C, 0x80, 0x06, 0x44, 0x48, 0x48, 0x50, 0x50, 0x70, 0xBC, 0x80, 0x09, 0x5B, 0x40, 0x01, 0x41, 0x40, 0x01, 0x41, 0x40, 0x01, 0x6D, 0x80, 0x03, 0x66, 0x66, 0x66, 0x24, 0x80, 0x08, 0x36, 0x36, 0x7F, 0x36, 0x36, 0x36, 0x7F, 0x36, 0x36, 0x80, 0x0D, 0x18, 0x18, 0x3E, 0x63, 0x43, 0x03, 0x3E, 0x60, 0x60, 0x61, 0x63, 0x3E, 0x18, 0x18, 0x80, 0x07, 0x43, 0x63, 0x30, 0x18, 0x0C, 0x06, 0x63, 0x61, 0x80, 0x09, 0x1C, 0x36, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x03, 0x0C, 0x0C, 0x0C, 0x04, 0x80, 0x09, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x80, 0x09, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x80, 0x04, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x80, 0x07, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0x09, 0x1C, 0x36, 0x63, 0x63, 0x6B, 0x6B, 0x63, 0x63, 0x36, 0x1C, 0x80, 0x09, 0x18, 0x1C, 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x80, 0x09, 0x3E, 0x63, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x63, 0x7F, 0x80, 0x09, 0x3E, 0x63, 0x60, 0x60, 0x3C, 0x60, 0x60, 0x60, 0x63, 0x3E, 0x80, 0x09, 0x30, 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x30, 0x30, 0x78, 0x80, 0x09, 0x7F, 0x03, 0x03, 0x03, 0x3F, 0x60, 0x60, 0x60, 0x63, 0x3E, 0x80, 0x09, 0x1C, 0x06, 0x03, 0x03, 0x3F, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x7F, 0x63, 0x60, 0x60, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x63, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x60, 0x30, 0x1E, 0x80, 0x08, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x80, 0x08, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x80, 0x06, 0x3E, 0x63, 0x63, 0x30, 0x18, 0x18, 0x18, 0x80, 0x08, 0x3E, 0x63, 0x63, 0x7B, 0x7B, 0x7B, 0x3B, 0x03, 0x3E, 0x80, 0x09, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x0B, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x6B, 0x7B, 0x3E, 0x30, 0x70, 0x80, 0x09, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x80, 0x08, 0x01, 0x03, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0x60, 0x40, 0x80, 0x09, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x80, 0x09, 0x1C, 0x36, 0x26, 0x06, 0x0F, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x09, 0x6E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x30, 0x78, 0x80, 0x09, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x70, 0x80, 0x09, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x80, 0x06, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x80, 0x0A, 0x18, 0x18, 0x3C, 0x66, 0x06, 0x06, 0x06, 0x66, 0x3C, 0x18, 0x18, 0x80, 0x0A, 0x1C, 0x36, 0x26, 0x06, 0x0F, 0x06, 0x06, 0x06, 0x06, 0x67, 0x3F, 0x80, 0x06, 0x66, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x66, 0x80, 0x09, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x80, 0x0B, 0x3E, 0x63, 0x06, 0x1C, 0x36, 0x63, 0x63, 0x36, 0x1C, 0x30, 0x63, 0x3E, 0x80, 0x09, 0x3C, 0x42, 0x99, 0xA5, 0x85, 0x85, 0xA5, 0x99, 0x42, 0x3C, 0x80, 0x03, 0x3C, 0x36, 0x36, 0x7C, 0x80, 0x04, 0x6C, 0x36, 0x1B, 0x36, 0x6C, 0x80, 0x04, 0x7F, 0x60, 0x60, 0x60, 0x60, 0x80, 0x06, 0x1C, 0x22, 0x5D, 0x4D, 0x55, 0x22, 0x1C, 0x80, 0x09, 0xFE, 0xDB, 0xDB, 0xDB, 0xDE, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0x80, 0x02, 0x18, 0x30, 0x1C, 0x80, 0x04, 0x1B, 0x36, 0x6C, 0x36, 0x1B, 0x80, 0x0C, 0x03, 0x03, 0x43, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x73, 0x79, 0x7C, 0x60, 0x60, 0x80, 0x0C, 0x03, 0x03, 0x43, 0x63, 0x33, 0x18, 0x0C, 0x06, 0x3B, 0x61, 0x30, 0x18, 0x7C, 0x80, 0x0C, 0x07, 0x0C, 0x46, 0x6C, 0x37, 0x18, 0x0C, 0x66, 0x73, 0x79, 0x7C, 0x60, 0x60, 0x80, 0x06, 0x0C, 0x0C, 0x06, 0x03, 0x63, 0x63, 0x3E, 0x80, 0x0B, 0x1C, 0x36, 0x1C, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x80, 0x0B, 0x18, 0x3C, 0x42, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x04, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x80, 0x09, 0x5E, 0x23, 0x73, 0x73, 0x6B, 0x6B, 0x67, 0x67, 0x62, 0x3D, 0x80, 0x0B, 0x08, 0x1C, 0x22, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x0F, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x0F, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x36, 0x66, 0x66, 0x66, 0x66, 0x37, 0x80, 0x09, 0x6E, 0x38, 0x3C, 0x60, 0x7E, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x0C, 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x80, 0x0C, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x30, 0x18, 0x70, 0x80, 0x09, 0x1E, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x6E, 0x30, 0x18, 0x70, 0x80, 0x0B, 0x08, 0x1C, 0x22, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3C, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3C, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x30, 0x30, 0x3C, 0x36, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x0B, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x66, 0x7F, 0x18, 0x0C, 0x38, 0x80, 0x09, 0x3E, 0x63, 0x7F, 0x03, 0x03, 0x63, 0x3E, 0x0C, 0x06, 0x1C, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x66, 0x7F, 0x80, 0x0B, 0x08, 0x1C, 0x22, 0x3C, 0x66, 0x43, 0x03, 0x7B, 0x63, 0x63, 0x66, 0x5C, 0x80, 0x01, 0x08, 0x1C, 0x80, 0x0B, 0x08, 0x1C, 0x22, 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x67, 0x80, 0x09, 0x66, 0xFF, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x66, 0x66, 0x80, 0x0B, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x18, 0x0C, 0x38, 0x80, 0x09, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x18, 0x0C, 0x38, 0x80, 0x09, 0xEF, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xDE, 0xDE, 0x77, 0x80, 0x09, 0x77, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6F, 0x60, 0x66, 0x3C, 0x80, 0x0B, 0x10, 0x38, 0x44, 0x78, 0x30, 0x30, 0x30, 0x30, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x02, 0x20, 0x70, 0xD8, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x0F, 0x06, 0x06, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x0F, 0x06, 0x06, 0x06, 0x66, 0x66, 0x06, 0x46, 0x66, 0x7F, 0x80, 0x09, 0x0E, 0x0C, 0x0C, 0x0C, 0x6C, 0x6C, 0x0C, 0x0C, 0x0C, 0x1E, 0x80, 0x09, 0x0F, 0x06, 0x06, 0x06, 0x1E, 0x07, 0x06, 0x46, 0x66, 0x7F, 0x80, 0x09, 0x1C, 0x18, 0x18, 0x18, 0x78, 0x1E, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x63, 0x67, 0x6F, 0x7F, 0x7B, 0x73, 0x63, 0x63, 0x63, 0x80, 0x02, 0x06, 0x06, 0x03, 0x80, 0x0C, 0x63, 0x67, 0x6F, 0x7F, 0x7B, 0x73, 0x63, 0x63, 0x63, 0x63, 0x60, 0x60, 0x38, 0x80, 0x09, 0x3B, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x38, 0x80, 0x09, 0x76, 0x1B, 0x1B, 0x1B, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x76, 0x80, 0x06, 0x36, 0x6B, 0x6B, 0x7B, 0x1B, 0x1B, 0x76, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x66, 0x67, 0x80, 0x0B, 0x08, 0x1C, 0x22, 0x3E, 0x63, 0x63, 0x06, 0x1C, 0x30, 0x63, 0x63, 0x3E, 0x80, 0x0B, 0x3E, 0x63, 0x63, 0x06, 0x1C, 0x30, 0x63, 0x63, 0x3E, 0x18, 0x30, 0x1C, 0x80, 0x09, 0x3E, 0x63, 0x06, 0x1C, 0x30, 0x63, 0x3E, 0x18, 0x30, 0x1C, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x3E, 0x63, 0x63, 0x06, 0x1C, 0x30, 0x63, 0x63, 0x3E, 0x80, 0x0C, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x18, 0x30, 0x1C, 0x80, 0x0C, 0x08, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x18, 0x30, 0x1C, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x08, 0x0C, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x80, 0x09, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x3C, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x08, 0x0C, 0x0C, 0x3F, 0x0C, 0x3F, 0x0C, 0x0C, 0x6C, 0x38, 0x80, 0x01, 0x33, 0x1E, 0x80, 0x0B, 0x1C, 0x36, 0x1C, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x0B, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x0C, 0x06, 0x1C, 0x80, 0x09, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x0C, 0x06, 0x1C, 0x80, 0x0B, 0x08, 0x1C, 0x22, 0x63, 0x63, 0x63, 0x6B, 0x6B, 0x6B, 0x7F, 0x77, 0x36, 0x80, 0x0B, 0x08, 0x1C, 0x22, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x7F, 0x63, 0x31, 0x18, 0x0C, 0x06, 0x43, 0x63, 0x7F, 0x80, 0x09, 0x1C, 0x36, 0x26, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x09, 0x06, 0x1F, 0x06, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x80, 0x09, 0x7E, 0xCD, 0xCD, 0xCC, 0x7C, 0xCC, 0xCC, 0xCC, 0xCC, 0x7E, 0x80, 0x09, 0x3F, 0x26, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3F, 0x80, 0x09, 0x7E, 0x46, 0x06, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x80, 0x09, 0x3E, 0x67, 0x67, 0x66, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3F, 0x80, 0x09, 0x06, 0x07, 0x07, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x80, 0x0A, 0xC0, 0x7C, 0x66, 0x43, 0x03, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3C, 0x80, 0x07, 0xC0, 0x7E, 0x63, 0x03, 0x03, 0x03, 0x63, 0x3E, 0x80, 0x09, 0x3E, 0x6D, 0xCD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x6C, 0x3E, 0x80, 0x09, 0x7E, 0x32, 0x30, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x7E, 0x80, 0x09, 0x3E, 0x32, 0x30, 0x3C, 0x36, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x0C, 0x18, 0x33, 0x1E, 0x80, 0x09, 0x7F, 0x33, 0x31, 0x34, 0x3C, 0x34, 0x30, 0x31, 0x33, 0x7F, 0x80, 0x0C, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x03, 0x80, 0x0C, 0x38, 0x6C, 0x4C, 0x0C, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x07, 0x80, 0x0A, 0xC0, 0x7C, 0x66, 0x43, 0x03, 0x03, 0x7B, 0x63, 0x63, 0x66, 0x5C, 0x80, 0x0B, 0x63, 0x63, 0x63, 0x36, 0x36, 0x36, 0x1C, 0x1C, 0x08, 0x1C, 0x36, 0x1C, 0x80, 0x09, 0x03, 0x03, 0x03, 0xCF, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x73, 0x80, 0x09, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x80, 0x09, 0x3C, 0x18, 0x18, 0x18, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x67, 0xB6, 0x36, 0x1E, 0x0E, 0x1E, 0x36, 0x66, 0x66, 0x67, 0x80, 0x09, 0x1C, 0x36, 0x06, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x67, 0x80, 0x09, 0x1C, 0x18, 0x18, 0x18, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x13, 0x1C, 0x0E, 0x0B, 0x1C, 0x1C, 0x36, 0x26, 0x63, 0x43, 0x80, 0x09, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x37, 0x80, 0x0C, 0x66, 0x66, 0x6E, 0x7E, 0x7E, 0x76, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x03, 0x80, 0x0C, 0xCE, 0xFB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0xC0, 0xC0, 0xC0, 0x80, 0x09, 0xCE, 0xFB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0xC0, 0xC0, 0xC0, 0x80, 0x09, 0x7E, 0xCD, 0xCD, 0xCC, 0x7C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x80, 0x0C, 0x1C, 0x36, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x80, 0x0A, 0x0F, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x1E, 0x36, 0x36, 0x67, 0x60, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x30, 0x1C, 0x06, 0x03, 0x63, 0x63, 0x3E, 0x80, 0x06, 0x3E, 0x63, 0x30, 0x1C, 0x06, 0x63, 0x3E, 0x80, 0x0C, 0x0E, 0x1B, 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0x70, 0x80, 0x0C, 0x08, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x30, 0x36, 0x1C, 0x80, 0x09, 0x7E, 0x7F, 0x59, 0x1A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x38, 0x6C, 0x0C, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x80, 0x0C, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x70, 0x80, 0x09, 0x33, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x33, 0x1E, 0x80, 0x09, 0xC6, 0xCD, 0xCD, 0xCC, 0x78, 0x30, 0x30, 0x30, 0x30, 0x78, 0x80, 0x0B, 0x60, 0xB0, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0F, 0x80, 0x09, 0x7F, 0x63, 0x61, 0x30, 0x7E, 0x0C, 0x06, 0x43, 0x63, 0x7F, 0x80, 0x06, 0x7F, 0x33, 0x18, 0x3F, 0x06, 0x63, 0x7F, 0x80, 0x0B, 0x7F, 0x60, 0x30, 0x18, 0x0C, 0x3E, 0x60, 0x60, 0x60, 0x60, 0x63, 0x3E, 0x80, 0x0B, 0x7F, 0x03, 0x06, 0x0C, 0x18, 0x3E, 0x03, 0x03, 0x03, 0x03, 0x63, 0x3E, 0x80, 0x09, 0x7F, 0x03, 0x06, 0x0C, 0x1E, 0x03, 0x03, 0x03, 0x63, 0x3E, 0x80, 0x09, 0x7F, 0x60, 0x30, 0x18, 0x3C, 0x60, 0x3E, 0x03, 0x63, 0x3E, 0x80, 0x09, 0x3E, 0x63, 0x60, 0x30, 0x7E, 0x0C, 0x06, 0x03, 0x63, 0x7F, 0x80, 0x09, 0x7F, 0x06, 0x06, 0x1E, 0x30, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x80, 0x06, 0x7F, 0x06, 0x1E, 0x30, 0x60, 0x66, 0x3C, 0x80, 0x09, 0x08, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x18, 0x32, 0x36, 0x1C, 0x80, 0x09, 0x3B, 0x66, 0x66, 0x66, 0x36, 0x1E, 0x0E, 0x06, 0x06, 0x0F, 0x80, 0x09, 0x18, 0x18, 0x18, 0x7E, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0B, 0xD8, 0x70, 0x20, 0xEF, 0x9B, 0x9B, 0x5B, 0x5B, 0x5B, 0x3B, 0x3B, 0xEF, 0x80, 0x09, 0xAF, 0x5B, 0x1B, 0xFB, 0x9B, 0x5B, 0x5B, 0x5B, 0x3B, 0xEF, 0x80, 0x09, 0xBC, 0x58, 0x18, 0xFE, 0x9B, 0x5B, 0x5B, 0x5B, 0x3B, 0xF6, 0x80, 0x09, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xD3, 0x6F, 0x80, 0x0C, 0xCF, 0xC6, 0x06, 0xE6, 0xC6, 0xC6, 0xC6, 0xE6, 0xF6, 0xFF, 0xC0, 0xD8, 0x70, 0x80, 0x0C, 0xC7, 0xC6, 0x06, 0xE6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xCF, 0xC0, 0xCC, 0x78, 0x80, 0x09, 0xDB, 0xDB, 0xDF, 0xDF, 0xDF, 0xDB, 0xDB, 0xDB, 0xDB, 0x7B, 0x80, 0x0C, 0xDB, 0xDB, 0x1F, 0xFF, 0xDF, 0xDF, 0xDB, 0xDB, 0xDB, 0xDB, 0xC0, 0xCC, 0x78, 0x80, 0x09, 0xED, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xC0, 0xCC, 0x78, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x02, 0x10, 0x08, 0x36, 0x80, 0x02, 0x14, 0x08, 0x36, 0x80, 0x01, 0x1E, 0x0C, 0x80, 0x02, 0x04, 0x08, 0x36, 0x80, 0x09, 0x36, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x80, 0x0B, 0x3E, 0x0C, 0x0C, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x80, 0x09, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x7B, 0x63, 0xFB, 0x66, 0x5C, 0x80, 0x09, 0x6E, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x7C, 0x33, 0x1E, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x3C, 0x66, 0x43, 0x03, 0x7B, 0x63, 0x63, 0x66, 0x5C, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x67, 0x66, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x66, 0x67, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x07, 0x06, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x67, 0x80, 0x0C, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x0C, 0x06, 0x1C, 0x80, 0x0B, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x0C, 0x06, 0x1C, 0x80, 0x0D, 0x36, 0x1C, 0x08, 0x7F, 0x30, 0x18, 0x0C, 0x3E, 0x60, 0x60, 0x60, 0x60, 0x63, 0x3E, 0x80, 0x02, 0xD8, 0x70, 0x20, 0x80, 0x09, 0xEF, 0x9B, 0x9B, 0x5B, 0x5B, 0x5B, 0x5B, 0x3B, 0x3B, 0xEF, 0x80, 0x09, 0x0F, 0x1B, 0x1B, 0xFB, 0x9B, 0x5B, 0x5B, 0x5B, 0x3B, 0xEF, 0x80, 0x09, 0x1B, 0x1B, 0x1B, 0xDB, 0xDF, 0xDB, 0xDB, 0xDB, 0xDB, 0x73, 0x80, 0x0C, 0x3F, 0x66, 0x66, 0x66, 0x66, 0x36, 0x1E, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x07, 0x80, 0x0B, 0x30, 0x18, 0x1C, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x80, 0x0B, 0x30, 0x18, 0x1C, 0x36, 0x1C, 0x1E, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x08, 0x5E, 0x23, 0x73, 0x73, 0x6B, 0x67, 0x67, 0x62, 0x3D, 0x80, 0x01, 0x1E, 0x33, 0x80, 0x0B, 0x3E, 0x63, 0x61, 0x60, 0x38, 0x2E, 0x60, 0x60, 0x60, 0x60, 0x38, 0x0F, 0x80, 0x08, 0x3E, 0x63, 0x60, 0x70, 0x3C, 0x60, 0x60, 0x38, 0x0F, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x80, 0x0B, 0x36, 0x1C, 0x08, 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x67, 0x80, 0x09, 0x36, 0x63, 0x63, 0x63, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x24, 0x66, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x80, 0x0B, 0x7F, 0x63, 0x61, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x03, 0x3F, 0x60, 0x30, 0x80, 0x08, 0x7F, 0x33, 0x18, 0x0C, 0x06, 0x03, 0x3F, 0x60, 0x30, 0x80, 0x0C, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x46, 0x66, 0x7F, 0x18, 0x30, 0x1C, 0x80, 0x06, 0x3B, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x3C, 0x80, 0x06, 0x2E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x06, 0x3B, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3A, 0x80, 0x09, 0x1C, 0x36, 0x06, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x80, 0x06, 0x3E, 0x63, 0x60, 0x60, 0x60, 0x63, 0x3E, 0x80, 0x07, 0x3E, 0x63, 0x03, 0x03, 0x3B, 0x67, 0x3E, 0x01, 0x80, 0x0C, 0x38, 0x30, 0x30, 0x3C, 0x36, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x30, 0xB0, 0x60, 0x80, 0x09, 0x60, 0xB0, 0x30, 0x3C, 0x36, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x06, 0x3E, 0x63, 0x7F, 0x60, 0x60, 0x63, 0x3E, 0x80, 0x06, 0xDC, 0x36, 0x71, 0x68, 0x64, 0x36, 0x1C, 0x80, 0x06, 0x5E, 0xB3, 0xB0, 0x1C, 0x30, 0x33, 0x1E, 0x80, 0x06, 0x3E, 0x63, 0x63, 0x3B, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x70, 0x60, 0x60, 0xF8, 0x60, 0x60, 0x60, 0x66, 0x66, 0x3C, 0x80, 0x0B, 0x60, 0xB0, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x33, 0x1E, 0x80, 0x06, 0x3E, 0x63, 0x03, 0x73, 0x63, 0x63, 0x5E, 0x80, 0x06, 0x43, 0x26, 0x14, 0x1C, 0x1C, 0x36, 0x1C, 0x80, 0x09, 0x73, 0x33, 0x33, 0x33, 0x33, 0x3B, 0x36, 0x30, 0x30, 0x70, 0x80, 0x09, 0x1C, 0x36, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x67, 0x80, 0x0C, 0x1C, 0x36, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x67, 0x60, 0x60, 0x38, 0x80, 0x06, 0x1C, 0x18, 0x18, 0x3C, 0x18, 0x18, 0x3C, 0x80, 0x06, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x1C, 0x18, 0x18, 0x18, 0xDE, 0x7B, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x1C, 0x18, 0x18, 0x18, 0x1E, 0x1A, 0x7C, 0x18, 0x18, 0x3C, 0x80, 0x0C, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0x70, 0x80, 0x0C, 0x07, 0x06, 0x06, 0xFE, 0xC6, 0x66, 0x36, 0x7E, 0xC6, 0xCF, 0xC0, 0xCC, 0x78, 0x80, 0x06, 0x63, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x76, 0x80, 0x09, 0x63, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x76, 0x60, 0x60, 0x60, 0x80, 0x09, 0x37, 0x7F, 0x6B, 0x6B, 0x6B, 0x6B, 0x63, 0x60, 0x60, 0x38, 0x80, 0x09, 0x3B, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x03, 0x80, 0x09, 0x3B, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0xC0, 0x80, 0x06, 0x63, 0x67, 0x6F, 0x7F, 0x7B, 0x73, 0x63, 0x80, 0x06, 0x76, 0x1B, 0x1B, 0x7B, 0x1B, 0x1B, 0x76, 0x80, 0x06, 0x78, 0x30, 0x30, 0x30, 0x33, 0x3B, 0x6E, 0x80, 0x09, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x3B, 0x6E, 0x80, 0x09, 0x78, 0x30, 0x30, 0x30, 0x33, 0x3B, 0x36, 0x30, 0xB0, 0x60, 0x80, 0x09, 0x3B, 0x6E, 0x66, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x09, 0x3B, 0x6E, 0x66, 0x06, 0x06, 0x06, 0x06, 0x06, 0x36, 0x1C, 0x80, 0x06, 0x3C, 0x66, 0x66, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x06, 0x1E, 0x33, 0x33, 0x30, 0x30, 0x30, 0x78, 0x80, 0x06, 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x80, 0x06, 0x67, 0x66, 0x36, 0x3E, 0x66, 0x66, 0x3F, 0x80, 0x09, 0x3E, 0x63, 0x06, 0x1C, 0x30, 0x63, 0x3F, 0x03, 0x1B, 0x0E, 0x80, 0x0C, 0x70, 0xD8, 0x98, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x1B, 0x0E, 0x80, 0x0C, 0x70, 0xD8, 0x98, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x19, 0x1B, 0x0E, 0x80, 0x07, 0x0E, 0x1B, 0x18, 0x18, 0x18, 0x18, 0xD8, 0x70, 0x80, 0x0A, 0x70, 0xD8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x1B, 0x0E, 0x80, 0x09, 0x0E, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x08, 0x80, 0x0C, 0x08, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x80, 0x06, 0x66, 0x66, 0x66, 0xFF, 0x66, 0x66, 0xDC, 0x80, 0x06, 0x77, 0x36, 0x36, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x06, 0x18, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x80, 0x06, 0x36, 0x7F, 0x6B, 0x6B, 0x6B, 0x63, 0x63, 0x80, 0x09, 0x7C, 0x06, 0x03, 0x3F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x80, 0x06, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x7F, 0x33, 0x18, 0x0C, 0x06, 0x63, 0x7F, 0x60, 0x60, 0xC0, 0x80, 0x07, 0x7F, 0x33, 0x18, 0x0C, 0x66, 0xD3, 0x7F, 0x08, 0x80, 0x09, 0x7F, 0x60, 0x30, 0x18, 0x3C, 0x60, 0x60, 0x7E, 0xE3, 0x3E, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x60, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x03, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x80, 0x09, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x38, 0x60, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x3E, 0x63, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x63, 0x3E, 0x80, 0x09, 0x3C, 0x66, 0xC3, 0xC3, 0xDB, 0xDB, 0xC3, 0xC3, 0x66, 0x3C, 0x80, 0x06, 0x3E, 0x63, 0x63, 0x6E, 0x63, 0x63, 0x3E, 0x80, 0x07, 0xC0, 0x7E, 0x63, 0x03, 0x73, 0x63, 0x63, 0x5E, 0x80, 0x01, 0x30, 0x30, 0x80, 0x09, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x7E, 0x33, 0x1E, 0x80, 0x09, 0x73, 0x33, 0x36, 0x3C, 0x3C, 0x36, 0x33, 0x30, 0x30, 0x70, 0x80, 0x06, 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x80, 0x0B, 0x60, 0xB0, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x30, 0x78, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x60, 0x38, 0x18, 0x7E, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x03, 0x0E, 0x0C, 0x3F, 0x0C, 0x0C, 0x1E, 0x80, 0x0C, 0x1C, 0x18, 0x18, 0xFE, 0xDB, 0xDB, 0x7B, 0x7B, 0xDB, 0xD6, 0xC0, 0xD8, 0x70, 0x80, 0x0A, 0x1C, 0x18, 0x18, 0xFE, 0x9B, 0x5B, 0x5B, 0xDB, 0xBB, 0xF6, 0x20, 0x80, 0x09, 0x04, 0x06, 0x06, 0x6F, 0xB6, 0x36, 0x66, 0xC6, 0xD6, 0x6C, 0x80, 0x0C, 0x64, 0xB6, 0x36, 0x3F, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3C, 0x30, 0x34, 0x18, 0x80, 0x09, 0x04, 0x06, 0x06, 0x6F, 0xB6, 0x36, 0x36, 0x76, 0xB6, 0x6C, 0x80, 0x0C, 0x0E, 0x1B, 0x03, 0x7F, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xC0, 0xC0, 0x70, 0x80, 0x09, 0x07, 0x06, 0x06, 0x66, 0xB6, 0x36, 0x66, 0xC6, 0xD6, 0x6F, 0x80, 0x09, 0x07, 0x06, 0x06, 0xF6, 0xD6, 0xC6, 0x66, 0x36, 0xB6, 0xFF, 0x80, 0x09, 0x63, 0x6B, 0x3E, 0x36, 0x14, 0x63, 0x6B, 0x3E, 0x36, 0x14, 0x80, 0x05, 0x03, 0x03, 0x0F, 0x1B, 0x1B, 0x1B, 0x80, 0x05, 0x0E, 0x03, 0x0F, 0x1B, 0x1B, 0x1B, 0x80, 0x04, 0x1C, 0x18, 0x18, 0x1B, 0x0E, 0x80, 0x03, 0x0D, 0x1B, 0x03, 0x03, 0x80, 0x03, 0x18, 0x18, 0x1B, 0x16, 0x80, 0x04, 0x18, 0x18, 0x1B, 0x16, 0x30, 0x80, 0x05, 0x1B, 0x1B, 0x0F, 0x1B, 0x1B, 0x0F, 0x80, 0x03, 0x63, 0x6B, 0x3E, 0x36, 0x80, 0x04, 0x1B, 0x1B, 0x1E, 0x18, 0x0E, 0x80, 0x02, 0x6C, 0x36, 0x1B, 0x80, 0x02, 0x0C, 0x06, 0x0C, 0x80, 0x04, 0x0E, 0x1B, 0x18, 0x0C, 0x0C, 0x80, 0x04, 0x0E, 0x1B, 0x03, 0x06, 0x06, 0x80, 0x04, 0x18, 0x0E, 0x03, 0x0E, 0x18, 0x80, 0x04, 0x03, 0x0E, 0x18, 0x0E, 0x03, 0x80, 0x05, 0x04, 0x04, 0x0E, 0x0E, 0x1B, 0x1B, 0x80, 0x05, 0x1B, 0x1B, 0x0E, 0x0E, 0x04, 0x04, 0x80, 0x01, 0x18, 0x30, 0x80, 0x01, 0x0C, 0x06, 0x80, 0x02, 0x18, 0x0C, 0x38, 0x80, 0x03, 0x36, 0x36, 0x36, 0x12, 0x80, 0x01, 0x2C, 0x1A, 0x80, 0x01, 0x03, 0x06, 0x80, 0x01, 0xC0, 0x60, 0x80, 0x02, 0x0C, 0x04, 0x02, 0x80, 0x02, 0x08, 0x04, 0x06, 0x80, 0x02, 0x0C, 0x2C, 0x18, 0x80, 0x01, 0x06, 0x03, 0x80, 0x0B, 0x06, 0x03, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x80, 0x0B, 0x06, 0x03, 0x7C, 0x4C, 0x0C, 0x2C, 0x3C, 0x2C, 0x0C, 0x0C, 0x4C, 0x7C, 0x80, 0x0B, 0x06, 0x03, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x80, 0x0B, 0x06, 0x03, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x0B, 0x06, 0x03, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x80, 0x0B, 0x06, 0x03, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x0B, 0x06, 0x03, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x6C, 0x6C, 0xEE, 0x80, 0x09, 0x08, 0x08, 0x1C, 0x1C, 0x36, 0x36, 0x63, 0x63, 0x63, 0x63, 0x80, 0x05, 0x7F, 0x63, 0x41, 0x22, 0x3E, 0x22, 0x80, 0x02, 0x41, 0x63, 0x7F, 0x80, 0x09, 0x08, 0x49, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3E, 0x08, 0x08, 0x80, 0x0C, 0x3C, 0x66, 0x66, 0x66, 0x36, 0x66, 0x66, 0x66, 0x66, 0x36, 0x06, 0x06, 0x06, 0x80, 0x09, 0x3C, 0x66, 0x0C, 0x18, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x0C, 0x62, 0x3E, 0x18, 0x0C, 0x06, 0x06, 0x03, 0x03, 0x03, 0x3E, 0x60, 0x60, 0x38, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x80, 0x09, 0x03, 0x04, 0x0C, 0x08, 0x1C, 0x1C, 0x36, 0x26, 0x63, 0x43, 0x80, 0x06, 0x63, 0x63, 0x66, 0x36, 0x3C, 0x1C, 0x08, 0x80, 0x0C, 0x66, 0x3C, 0x0C, 0x06, 0x3C, 0x06, 0x03, 0x03, 0x03, 0x3E, 0x60, 0x60, 0x38, 0x80, 0x06, 0x7F, 0x36, 0x36, 0x36, 0x36, 0x36, 0x66, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x80, 0x08, 0x3E, 0x63, 0x03, 0x03, 0x03, 0x3E, 0x60, 0x60, 0x38, 0x80, 0x06, 0x7E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x06, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x70, 0x80, 0x09, 0x36, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3E, 0x08, 0x08, 0x08, 0x80, 0x09, 0x61, 0x62, 0x34, 0x34, 0x18, 0x0C, 0x16, 0x16, 0x23, 0x43, 0x80, 0x09, 0x49, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3E, 0x08, 0x08, 0x08, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x36, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x6C, 0x78, 0x63, 0x66, 0x66, 0x66, 0x3C, 0x80, 0x09, 0x43, 0xA6, 0x24, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x0B, 0x06, 0x03, 0x84, 0x4C, 0x48, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x80, 0x08, 0x43, 0xA6, 0x24, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x06, 0x7F, 0x36, 0x63, 0x6B, 0x6B, 0x6B, 0x36, 0x80, 0x08, 0x62, 0x65, 0x34, 0x1C, 0x16, 0x53, 0x23, 0x30, 0x18, 0x80, 0x0B, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x03, 0x03, 0x06, 0x3C, 0x60, 0x60, 0x38, 0x80, 0x09, 0x7E, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3E, 0x60, 0x60, 0x38, 0x80, 0x09, 0x7F, 0x66, 0x46, 0x06, 0x1E, 0x16, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x09, 0x7E, 0x4C, 0x0C, 0x0C, 0x3C, 0x2C, 0x0C, 0x0C, 0x0C, 0x0C, 0x80, 0x0A, 0x06, 0x0C, 0x0C, 0x06, 0xC6, 0xFF, 0x63, 0x60, 0x30, 0x30, 0x60, 0x80, 0x09, 0x0C, 0x0C, 0x06, 0x06, 0x7F, 0x7F, 0x30, 0x30, 0x18, 0x18, 0x80, 0x0C, 0x1E, 0x35, 0x64, 0x64, 0xD0, 0xD0, 0xD8, 0xD8, 0xD8, 0xD8, 0xC0, 0x40, 0x20, 0x80, 0x0A, 0x03, 0x06, 0x0C, 0x18, 0x14, 0x32, 0x28, 0x24, 0x60, 0x40, 0x40, 0x80, 0x0B, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xB6, 0xC0, 0x7C, 0x80, 0x08, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xB6, 0xC0, 0x7E, 0x80, 0x09, 0x6E, 0x6B, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x60, 0x60, 0x80, 0x09, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x60, 0x80, 0x0C, 0x03, 0x03, 0x03, 0x03, 0x3F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x60, 0x6E, 0x39, 0x80, 0x07, 0x10, 0x3E, 0x6B, 0x66, 0x60, 0x60, 0x66, 0x3D, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x60, 0x3C, 0x06, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x64, 0x38, 0x0E, 0x03, 0x43, 0x63, 0x3E, 0x80, 0x09, 0x63, 0x16, 0x1C, 0x0C, 0x1C, 0x1C, 0x32, 0x32, 0x61, 0x7F, 0x80, 0x06, 0x26, 0x5D, 0x0C, 0x1C, 0x14, 0x32, 0x3E, 0x80, 0x09, 0x7E, 0x03, 0x33, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x06, 0x7E, 0x03, 0x3B, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x3C, 0x18, 0x7E, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x18, 0x38, 0x18, 0x7E, 0x1A, 0x18, 0x18, 0x18, 0x1C, 0x18, 0x80, 0x06, 0x62, 0x65, 0x34, 0x1C, 0x16, 0x53, 0x23, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x3F, 0x03, 0x06, 0x3C, 0x60, 0x80, 0x0B, 0x7F, 0x4D, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xC0, 0x60, 0x80, 0x08, 0x7F, 0x66, 0x46, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x09, 0x3C, 0x66, 0x43, 0x03, 0x1F, 0x03, 0x03, 0x43, 0x66, 0x3C, 0x80, 0x09, 0x1E, 0x1B, 0x1B, 0x1B, 0x7B, 0xDB, 0xDB, 0xDB, 0xDB, 0x7B, 0x80, 0x09, 0x1B, 0x1B, 0x1B, 0x1B, 0x7F, 0xDB, 0xDB, 0xDB, 0xDB, 0x7B, 0x80, 0x09, 0x7F, 0x4D, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x80, 0x0C, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x1C, 0x08, 0x08, 0x80, 0x09, 0x7F, 0x66, 0x46, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3F, 0x80, 0x0B, 0x3C, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x7F, 0x63, 0x41, 0x80, 0x09, 0x6B, 0x6B, 0x6B, 0x3E, 0x1C, 0x3E, 0x6B, 0x6B, 0x6B, 0x6B, 0x80, 0x09, 0x3E, 0x63, 0x61, 0x60, 0x3C, 0x60, 0x60, 0x61, 0x63, 0x3E, 0x80, 0x09, 0x63, 0x63, 0x63, 0x73, 0x7B, 0x7F, 0x6F, 0x67, 0x63, 0x63, 0x80, 0x0B, 0x36, 0x1C, 0x63, 0x63, 0x63, 0x73, 0x7B, 0x7F, 0x6F, 0x67, 0x63, 0x63, 0x80, 0x09, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x63, 0x80, 0x09, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x63, 0x3E, 0x80, 0x0B, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x7F, 0x60, 0x40, 0x80, 0x09, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x60, 0x60, 0x80, 0x09, 0x63, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x80, 0x0B, 0x63, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0xFF, 0xC0, 0x80, 0x80, 0x09, 0x1F, 0x0D, 0x0D, 0x0C, 0x3C, 0x6C, 0x6C, 0x6C, 0x6C, 0x3E, 0x80, 0x09, 0xC3, 0xC3, 0xC3, 0xC3, 0xCF, 0xDB, 0xDB, 0xDB, 0xDB, 0xCF, 0x80, 0x09, 0x0F, 0x06, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3F, 0x80, 0x09, 0x1E, 0x33, 0x61, 0x60, 0x7C, 0x60, 0x60, 0x61, 0x33, 0x1E, 0x80, 0x09, 0x39, 0x6D, 0x6D, 0x6D, 0x6F, 0x6D, 0x6D, 0x6D, 0x6D, 0x39, 0x80, 0x09, 0x7E, 0x33, 0x33, 0x33, 0x3E, 0x36, 0x36, 0x36, 0x36, 0x73, 0x80, 0x09, 0x60, 0x3E, 0x03, 0x03, 0x3F, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x08, 0x3C, 0x36, 0x36, 0x36, 0x36, 0x36, 0x7F, 0x63, 0x41, 0x80, 0x06, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x63, 0x80, 0x06, 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x80, 0x06, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x80, 0x06, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x0A, 0x08, 0x3E, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3E, 0x08, 0x08, 0x08, 0x80, 0x08, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x7F, 0x60, 0x40, 0x80, 0x06, 0x63, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x80, 0x08, 0x63, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0xFF, 0xC0, 0x80, 0x80, 0x06, 0x1F, 0x0D, 0x0C, 0x3C, 0x6C, 0x6C, 0x3E, 0x80, 0x06, 0x0F, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3F, 0x80, 0x06, 0x39, 0x6D, 0x6D, 0x6F, 0x6D, 0x6D, 0x39, 0x80, 0x06, 0x7E, 0x33, 0x33, 0x3E, 0x36, 0x36, 0x73, 0x80, 0x0C, 0x06, 0x1F, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x67, 0x60, 0x60, 0x38, 0x80, 0x06, 0x3E, 0x63, 0x03, 0x1F, 0x03, 0x63, 0x3E, 0x80, 0x06, 0x1E, 0x1B, 0x1B, 0x7B, 0xDB, 0xDB, 0x7B, 0x80, 0x06, 0x1B, 0x1B, 0x1B, 0x7F, 0xDB, 0xDB, 0x7B, 0x80, 0x09, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x1C, 0x08, 0x08, 0x80, 0x09, 0x36, 0x63, 0x63, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x36, 0x80, 0x09, 0x0C, 0x3F, 0x2D, 0x0C, 0x3C, 0x6C, 0x6C, 0x6C, 0x6C, 0x3E, 0x80, 0x09, 0x0C, 0x0C, 0x0C, 0x3F, 0x2D, 0x0C, 0x3C, 0x6C, 0x6C, 0x3E, 0x80, 0x09, 0x73, 0xDB, 0x9B, 0x1B, 0x7F, 0x1B, 0x1B, 0x9B, 0xDB, 0x73, 0x80, 0x06, 0x73, 0xDB, 0x1B, 0x7F, 0x1B, 0xDB, 0x73, 0x80, 0x09, 0x08, 0x1C, 0x1C, 0x36, 0x36, 0x36, 0x7F, 0x6B, 0x6B, 0x6B, 0x80, 0x06, 0x08, 0x1C, 0x1C, 0x36, 0x3E, 0x6B, 0x6B, 0x80, 0x09, 0x11, 0x31, 0x39, 0x69, 0x6F, 0x6D, 0xFD, 0xD5, 0xD7, 0xD7, 0x80, 0x06, 0x11, 0x31, 0x39, 0x6F, 0x7D, 0xD5, 0xD7, 0x80, 0x09, 0x7F, 0x63, 0x36, 0x36, 0x1C, 0x3E, 0x6B, 0x6B, 0x6B, 0x6B, 0x80, 0x06, 0x7F, 0x63, 0x36, 0x3E, 0x6B, 0x6B, 0x6B, 0x80, 0x09, 0xFF, 0xC5, 0x4D, 0x69, 0x3F, 0x39, 0x7D, 0x55, 0xD5, 0xD7, 0x80, 0x06, 0xFD, 0xC5, 0x69, 0x7F, 0xD5, 0xD5, 0xD7, 0x80, 0x0D, 0x36, 0x1C, 0x08, 0x3E, 0x63, 0x60, 0x60, 0x3E, 0x60, 0x60, 0x60, 0x3E, 0x03, 0x3E, 0x80, 0x08, 0x3E, 0x61, 0x60, 0x3E, 0x60, 0x60, 0x3E, 0x03, 0x3E, 0x80, 0x09, 0x08, 0x69, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3E, 0x08, 0x08, 0x80, 0x0C, 0x08, 0x08, 0x08, 0x69, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3E, 0x08, 0x08, 0x08, 0x80, 0x09, 0x43, 0x63, 0x63, 0x23, 0x33, 0x36, 0x16, 0x1E, 0x1C, 0x0C, 0x80, 0x08, 0x43, 0x63, 0x23, 0x23, 0x36, 0x16, 0x1E, 0x1C, 0x0C, 0x80, 0x0C, 0x0E, 0x1B, 0x1B, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xF6, 0xC0, 0x60, 0x38, 0x80, 0x09, 0xCE, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xF6, 0xC0, 0x60, 0x38, 0x80, 0x0B, 0x08, 0x3E, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x6B, 0x3E, 0x08, 0x80, 0x08, 0x08, 0x3E, 0x6B, 0x63, 0x63, 0x63, 0x6B, 0x3E, 0x08, 0x80, 0x0B, 0x20, 0x3E, 0x02, 0x36, 0x63, 0x63, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x36, 0x80, 0x08, 0x36, 0x63, 0x63, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x36, 0x80, 0x0C, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x3C, 0x30, 0x30, 0x30, 0x80, 0x08, 0x3E, 0x63, 0x03, 0x03, 0x03, 0x03, 0x1E, 0x18, 0x18, 0x80, 0x09, 0x60, 0x60, 0x3C, 0xF0, 0x18, 0x18, 0x0F, 0x3C, 0x06, 0x06, 0x80, 0x02, 0x18, 0x24, 0x22, 0x80, 0x02, 0x02, 0x3E, 0x02, 0x80, 0x02, 0x20, 0x3E, 0x20, 0x80, 0x00, 0xC3, 0x80, 0x02, 0x10, 0x0A, 0x62, 0x80, 0x01, 0x41, 0x82, 0x80, 0x02, 0x46, 0x50, 0x08, 0x80, 0x0D, 0x36, 0x1C, 0x63, 0x63, 0x63, 0x73, 0x7B, 0x7F, 0x6F, 0x67, 0x63, 0xE3, 0xC0, 0x80, 0x80, 0x08, 0x63, 0x73, 0x7B, 0x7F, 0x6F, 0x67, 0xE3, 0xC0, 0x80, 0x80, 0x0A, 0x06, 0x0F, 0x06, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3F, 0x80, 0x07, 0x06, 0x0F, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3F, 0x80, 0x09, 0x3F, 0x66, 0x76, 0x26, 0x5E, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x09, 0x3B, 0x66, 0x66, 0x66, 0x76, 0x26, 0x5E, 0x06, 0x06, 0x0F, 0x80, 0x0B, 0x40, 0x60, 0x7F, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x08, 0x40, 0x60, 0x7F, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x09, 0x7F, 0x66, 0x46, 0x06, 0x1F, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x06, 0x7F, 0x66, 0x46, 0x1F, 0x06, 0x06, 0x0F, 0x80, 0x0C, 0x7F, 0x66, 0x46, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x6F, 0x60, 0x68, 0x30, 0x80, 0x09, 0x7F, 0x66, 0x46, 0x1E, 0x36, 0x66, 0x6F, 0x60, 0x68, 0x30, 0x80, 0x0B, 0x6B, 0x6B, 0x6B, 0x3E, 0x1C, 0x3E, 0x6B, 0x6B, 0x6B, 0xEB, 0xC0, 0x80, 0x80, 0x08, 0x6B, 0x6B, 0x6B, 0x3E, 0x6B, 0x6B, 0xEB, 0xC0, 0x80, 0x80, 0x0C, 0x3E, 0x63, 0x61, 0x60, 0x3C, 0x60, 0x60, 0x61, 0x63, 0x3E, 0x0C, 0x06, 0x1C, 0x80, 0x09, 0x3E, 0x63, 0x60, 0x3C, 0x60, 0x63, 0x3E, 0x0C, 0x06, 0x1C, 0x80, 0x0B, 0x67, 0x66, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x66, 0xE7, 0xC0, 0x80, 0x80, 0x08, 0x67, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0xE7, 0xC0, 0x80, 0x80, 0x09, 0x63, 0x6B, 0x6B, 0x3B, 0x1F, 0x3B, 0x6B, 0x6B, 0x63, 0x63, 0x80, 0x06, 0x63, 0x6B, 0x3B, 0x1F, 0x3B, 0x6B, 0x63, 0x80, 0x09, 0x67, 0x66, 0x6F, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x66, 0x67, 0x80, 0x09, 0x07, 0x06, 0x0F, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x67, 0x80, 0x09, 0xCF, 0xCD, 0xCD, 0x6C, 0x3C, 0x3C, 0x6C, 0xCC, 0xCC, 0xCE, 0x80, 0x06, 0xCF, 0x6D, 0x3D, 0x3C, 0x6C, 0xCC, 0xCE, 0x80, 0x09, 0xFB, 0xDB, 0x9B, 0x1B, 0x1F, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x80, 0x06, 0xFB, 0xDB, 0x9B, 0x1F, 0x1B, 0x1B, 0x1B, 0x80, 0x0C, 0x1F, 0x1B, 0x1B, 0x1B, 0x7B, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xC0, 0xD0, 0x60, 0x80, 0x09, 0x1B, 0x1B, 0x1B, 0x7F, 0xDB, 0xDB, 0xDB, 0xC0, 0xD0, 0x60, 0x80, 0x09, 0x3E, 0x43, 0x33, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x33, 0x5E, 0x80, 0x06, 0x3E, 0x43, 0x33, 0x6B, 0x6B, 0x33, 0x5E, 0x80, 0x0B, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x30, 0x20, 0x80, 0x08, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x30, 0x20, 0x80, 0x09, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x3C, 0x80, 0x0B, 0x63, 0x63, 0x36, 0x3E, 0x1C, 0x1C, 0x3E, 0x36, 0x63, 0xE3, 0xC0, 0x80, 0x80, 0x08, 0x63, 0x36, 0x1C, 0x1C, 0x1C, 0x36, 0xE3, 0xC0, 0x80, 0x80, 0x0B, 0x6F, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFE, 0xC0, 0x80, 0x80, 0x08, 0x6F, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFE, 0xC0, 0x80, 0x80, 0x0B, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x60, 0xE0, 0xC0, 0x80, 0x80, 0x08, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0xE0, 0xC0, 0x80, 0x80, 0x09, 0x63, 0x63, 0x63, 0x6B, 0x6B, 0x7E, 0x68, 0x68, 0x60, 0x60, 0x80, 0x06, 0x63, 0x6B, 0x6B, 0x7E, 0x68, 0x68, 0x60, 0x80, 0x09, 0x03, 0x03, 0x03, 0x03, 0x3F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x80, 0x06, 0x03, 0x03, 0x03, 0x3F, 0x63, 0x63, 0x63, 0x80, 0x09, 0x78, 0xCC, 0xCD, 0xCD, 0xFE, 0x0C, 0x0C, 0x0C, 0xCC, 0x78, 0x80, 0x06, 0x79, 0xCD, 0xFE, 0x0C, 0x0C, 0xCC, 0x78, 0x80, 0x0C, 0x78, 0xCC, 0xCD, 0xCD, 0xFE, 0x0C, 0x0C, 0x0C, 0xCC, 0x78, 0x30, 0x18, 0x70, 0x80, 0x09, 0x79, 0xCD, 0xFE, 0x0C, 0x0C, 0xCC, 0x78, 0x30, 0x18, 0x70, 0x80, 0x0B, 0x36, 0x1C, 0x6B, 0x6B, 0x6B, 0x3E, 0x1C, 0x3E, 0x6B, 0x6B, 0x6B, 0x6B, 0x80, 0x0C, 0x67, 0x66, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x66, 0x67, 0x60, 0x68, 0x30, 0x80, 0x09, 0x67, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x67, 0x60, 0x68, 0x30, 0x80, 0x0B, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xE3, 0xC0, 0x80, 0x80, 0x08, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x66, 0xE3, 0xC0, 0x80, 0x80, 0x0C, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x60, 0x68, 0x30, 0x80, 0x09, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x60, 0x68, 0x30, 0x80, 0x0B, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x60, 0x70, 0x30, 0x10, 0x80, 0x08, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x70, 0x30, 0x10, 0x80, 0x0B, 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x63, 0xE3, 0xC0, 0x80, 0x80, 0x08, 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0xE3, 0xC0, 0x80, 0x80, 0x08, 0x3E, 0x63, 0x60, 0x60, 0x7F, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x08, 0x6B, 0x6B, 0x6B, 0x3E, 0x1C, 0x3E, 0x6B, 0x6B, 0x6B, 0x80, 0x08, 0x3E, 0x63, 0x61, 0x60, 0x3C, 0x60, 0x61, 0x63, 0x3E, 0x80, 0x09, 0x7F, 0x60, 0x30, 0x18, 0x3C, 0x60, 0x60, 0x61, 0x63, 0x3E, 0x80, 0x08, 0x3E, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x08, 0x1E, 0x33, 0x61, 0x60, 0x7C, 0x60, 0x61, 0x33, 0x1E, 0x80, 0x08, 0x63, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x60, 0x60, 0x80, 0x08, 0xC3, 0xC3, 0xC3, 0xCF, 0xDB, 0xDB, 0xDB, 0xDB, 0xCF, 0x80, 0x09, 0x78, 0x30, 0x30, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x7E, 0x80, 0x09, 0x78, 0x30, 0x30, 0x30, 0x3E, 0xB3, 0xB3, 0xB3, 0xB3, 0x6E, 0x80, 0x09, 0x38, 0x30, 0x30, 0x3C, 0x36, 0x33, 0xB3, 0xB3, 0xB3, 0x6E, 0x80, 0x09, 0x1E, 0x33, 0x31, 0x30, 0x1C, 0xB0, 0xB0, 0xB0, 0xB0, 0x60, 0x80, 0x06, 0x1E, 0x33, 0x30, 0x9C, 0xB0, 0xB0, 0x60, 0x80, 0x0B, 0x3E, 0x63, 0x61, 0x60, 0x3C, 0x60, 0x60, 0x60, 0x60, 0xE0, 0xC0, 0x80, 0x80, 0x08, 0x3E, 0x63, 0x60, 0x3C, 0x60, 0x60, 0xE0, 0xC0, 0x80, 0x80, 0x09, 0x3C, 0x36, 0x36, 0x36, 0x36, 0xB6, 0xB6, 0xB6, 0xB6, 0x63, 0x80, 0x06, 0x3C, 0x36, 0x36, 0xB6, 0xB6, 0xB6, 0x63, 0x80, 0x09, 0x33, 0x33, 0x33, 0x33, 0x3F, 0xB3, 0xB3, 0xB3, 0xB3, 0x63, 0x80, 0x06, 0x33, 0x33, 0x33, 0xBF, 0xB3, 0xB3, 0x63, 0x80, 0x09, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x73, 0x63, 0x63, 0x66, 0x3C, 0x80, 0x06, 0x3E, 0x63, 0x03, 0x73, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0xD8, 0xD8, 0xD8, 0xD8, 0x70, 0x80, 0x06, 0x7E, 0x5A, 0x18, 0xD8, 0xD8, 0xD8, 0x70, 0x80, 0x06, 0x18, 0x26, 0x29, 0x5D, 0x4A, 0x32, 0x0C, 0x80, 0x09, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xF3, 0xDE, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x7E, 0x06, 0x06, 0x80, 0x09, 0x1E, 0x33, 0x33, 0x33, 0x33, 0xFE, 0x30, 0x30, 0x30, 0x30, 0x80, 0x09, 0x1E, 0x33, 0x33, 0x33, 0x33, 0xF3, 0x30, 0x30, 0x30, 0x30, 0x80, 0x09, 0x06, 0x7E, 0x06, 0x06, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x80, 0x0A, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x30, 0x1B, 0x7F, 0xC3, 0x80, 0x0A, 0x06, 0x06, 0x7E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3E, 0x60, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x7E, 0x80, 0x09, 0x3E, 0x63, 0xF3, 0x6B, 0x6B, 0x6B, 0x6B, 0x33, 0x03, 0x03, 0x80, 0x09, 0x30, 0x30, 0x30, 0x30, 0xFE, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x09, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x80, 0x0A, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3E, 0x60, 0x80, 0x09, 0x03, 0x03, 0x6F, 0x6B, 0x6B, 0x6B, 0x6B, 0x33, 0x03, 0x03, 0x80, 0x09, 0x03, 0xFE, 0x24, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x80, 0x09, 0x06, 0x06, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x80, 0x0A, 0x18, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x0F, 0x3C, 0x70, 0x20, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x36, 0x1B, 0x76, 0x80, 0x09, 0x1E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x30, 0x30, 0x30, 0xF0, 0x80, 0x09, 0x78, 0x0C, 0x06, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x7E, 0x80, 0x09, 0xF3, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x09, 0x3C, 0x66, 0x60, 0x60, 0x3E, 0x60, 0x60, 0x66, 0x66, 0x3C, 0x80, 0x09, 0x07, 0x06, 0x06, 0x06, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x80, 0x09, 0x3C, 0x60, 0x7C, 0x66, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x36, 0x1C, 0x70, 0x80, 0x09, 0x3E, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x68, 0x68, 0x60, 0x60, 0x80, 0x0A, 0x3C, 0x66, 0x66, 0x66, 0x6E, 0x78, 0x70, 0x30, 0x1B, 0x7F, 0xC3, 0x80, 0x09, 0x1E, 0x33, 0x33, 0x33, 0x33, 0xF3, 0x33, 0x33, 0x33, 0x33, 0x80, 0x09, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x80, 0x09, 0x30, 0x30, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x30, 0xF0, 0x80, 0x09, 0x3E, 0x63, 0x63, 0x06, 0x0C, 0x18, 0x30, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x06, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x66, 0x60, 0x60, 0x66, 0x3C, 0x80, 0x09, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0xC6, 0x06, 0x06, 0x80, 0x09, 0x08, 0x3E, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3E, 0x08, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x7F, 0x06, 0x06, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x80, 0x09, 0x0E, 0x0B, 0x0B, 0x0B, 0x3E, 0x68, 0x68, 0x68, 0x6B, 0x3E, 0x80, 0x03, 0x18, 0x0C, 0x0C, 0x18, 0x80, 0x03, 0x0C, 0x18, 0x18, 0x0C, 0x80, 0x02, 0x60, 0x3C, 0x06, 0x80, 0x02, 0x0C, 0x18, 0x30, 0x80, 0x02, 0x38, 0x6C, 0x36, 0x80, 0x02, 0x0E, 0x06, 0x7C, 0x80, 0x06, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x56, 0x80, 0x09, 0x3E, 0x66, 0x66, 0x66, 0x06, 0x06, 0x7E, 0x06, 0x06, 0x06, 0x80, 0x09, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x33, 0xFE, 0x30, 0x30, 0x30, 0x80, 0x09, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x33, 0xF3, 0x30, 0x30, 0x30, 0x80, 0x09, 0x06, 0x06, 0x7E, 0x06, 0x06, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x80, 0x09, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x30, 0xF0, 0x80, 0x0B, 0x06, 0x06, 0x06, 0x3E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x30, 0x18, 0x80, 0x09, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x7E, 0x80, 0x09, 0x3F, 0x63, 0x63, 0xF3, 0x6B, 0x6B, 0x33, 0x03, 0x03, 0x03, 0x80, 0x09, 0x30, 0x30, 0x30, 0xFE, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x80, 0x0C, 0x06, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x80, 0x09, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x7C, 0x80, 0x0C, 0x03, 0x03, 0x03, 0x6F, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x53, 0x03, 0x03, 0x03, 0x80, 0x09, 0x06, 0x1C, 0x30, 0xFE, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x0C, 0x06, 0x06, 0x06, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x80, 0x09, 0x06, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x80, 0x09, 0x0C, 0x38, 0x30, 0x18, 0x3C, 0x26, 0x66, 0x46, 0xC6, 0xBC, 0x80, 0x09, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x30, 0x30, 0xF0, 0x80, 0x09, 0x70, 0x18, 0x0C, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x80, 0x09, 0xF0, 0x30, 0x30, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x80, 0x09, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x80, 0x09, 0x07, 0x06, 0x06, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x7C, 0x80, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x80, 0x09, 0x30, 0x18, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x7C, 0x80, 0x09, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x7E, 0x60, 0x60, 0x60, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x6E, 0x38, 0x18, 0x0C, 0x06, 0x7C, 0x80, 0x06, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x33, 0xF3, 0x80, 0x06, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x80, 0x0C, 0x30, 0x30, 0x30, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x30, 0xF0, 0x80, 0x06, 0x3B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6E, 0x80, 0x09, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x80, 0x09, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x66, 0x3C, 0x80, 0x06, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x7C, 0x80, 0x0C, 0x08, 0x08, 0x08, 0x3B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6E, 0x08, 0x08, 0x08, 0x80, 0x09, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x7F, 0x06, 0x06, 0x80, 0x06, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x80, 0x0C, 0x0E, 0x0B, 0x0B, 0x3E, 0x68, 0x68, 0x68, 0x68, 0x6B, 0x3E, 0x08, 0x08, 0x08, 0x80, 0x09, 0x03, 0x03, 0x03, 0x03, 0x03, 0x33, 0x33, 0x33, 0x33, 0xEE, 0x80, 0x02, 0x03, 0x63, 0x3E, 0x80, 0x03, 0x08, 0x08, 0x1C, 0x36, 0x80, 0x04, 0x10, 0x1C, 0x08, 0x1C, 0x04, 0x80, 0x02, 0x36, 0x06, 0x36, 0x80, 0x02, 0x08, 0x18, 0x30, 0x80, 0x02, 0x08, 0x1C, 0x08, 0x80, 0x02, 0x2E, 0x6B, 0x3A, 0x80, 0x02, 0x03, 0x06, 0x04, 0x80, 0x02, 0xC0, 0x60, 0xC0, 0x80, 0x02, 0x14, 0x18, 0x0C, 0x80, 0x02, 0x30, 0x18, 0x08, 0x80, 0x02, 0xC0, 0x60, 0x20, 0x80, 0x02, 0xD8, 0x6C, 0x24, 0x80, 0x03, 0x22, 0x55, 0x36, 0x14, 0x80, 0x03, 0x20, 0x50, 0x30, 0x10, 0x80, 0x03, 0x02, 0x0A, 0x07, 0x01, 0x80, 0x02, 0x08, 0x0C, 0x06, 0x80, 0x02, 0x24, 0x36, 0x1B, 0x80, 0x03, 0x18, 0x0C, 0x10, 0x0C, 0x80, 0x02, 0x06, 0x0C, 0x08, 0x80, 0x03, 0x02, 0x05, 0x06, 0x04, 0x80, 0x03, 0x36, 0x1C, 0x08, 0x08, 0x80, 0x02, 0x20, 0x60, 0xC0, 0x80, 0x02, 0x12, 0x15, 0x09, 0x80, 0x00, 0xDB, 0x80, 0x00, 0xCC, 0x80, 0x00, 0x6F, 0x80, 0x00, 0x60, 0x80, 0x02, 0x6F, 0x06, 0x66, 0x80, 0x02, 0x7E, 0x18, 0x18, 0x80, 0x02, 0x03, 0x18, 0xC0, 0x80, 0x01, 0x7E, 0x3F, 0x80, 0x07, 0x63, 0x63, 0x66, 0x6E, 0x3B, 0x33, 0x63, 0x63, 0x80, 0x07, 0x1F, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x7F, 0x80, 0x07, 0x1C, 0x30, 0x30, 0x30, 0x30, 0x38, 0x6C, 0x67, 0x80, 0x07, 0x7F, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x80, 0x07, 0x3F, 0x60, 0x60, 0x60, 0x63, 0x63, 0x63, 0x63, 0x80, 0x07, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x07, 0x7E, 0x18, 0x18, 0x18, 0x30, 0x30, 0x18, 0x0C, 0x80, 0x07, 0x3F, 0x66, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x80, 0x07, 0x33, 0x6B, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x04, 0x0E, 0x18, 0x18, 0x18, 0x0C, 0x80, 0x0A, 0x3F, 0x60, 0x60, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x70, 0x80, 0x07, 0x3F, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x3F, 0x80, 0x09, 0x03, 0x03, 0x3F, 0x60, 0x60, 0x60, 0x60, 0x30, 0x18, 0x18, 0x80, 0x07, 0x3F, 0x66, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x80, 0x07, 0x3B, 0x6E, 0x66, 0x63, 0x63, 0x63, 0x63, 0x7B, 0x80, 0x0A, 0x1C, 0x30, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0x80, 0x07, 0x1C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3E, 0x80, 0x07, 0x3F, 0x66, 0x63, 0x63, 0x63, 0x63, 0x33, 0x1E, 0x80, 0x07, 0x77, 0x66, 0x66, 0x66, 0x66, 0x66, 0x34, 0x1F, 0x80, 0x0A, 0x1F, 0x32, 0x33, 0x33, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x70, 0x80, 0x07, 0x3F, 0x62, 0x63, 0x63, 0x67, 0x60, 0x60, 0x7F, 0x80, 0x0A, 0x77, 0x66, 0x66, 0x36, 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0E, 0x80, 0x07, 0x77, 0x66, 0x66, 0x2C, 0x18, 0x30, 0x60, 0x7F, 0x80, 0x0A, 0x3F, 0x60, 0x60, 0x66, 0x26, 0x36, 0x76, 0x06, 0x06, 0x06, 0x06, 0x80, 0x07, 0x3F, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x80, 0x07, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6F, 0x63, 0x3E, 0x80, 0x07, 0x3F, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x67, 0x80, 0x07, 0x33, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x80, 0x07, 0x33, 0x66, 0x66, 0x66, 0x63, 0x60, 0x60, 0x60, 0x80, 0x04, 0x33, 0x66, 0x66, 0x66, 0x33, 0x80, 0x03, 0x10, 0x08, 0x18, 0x18, 0x80, 0x02, 0x30, 0x18, 0x18, 0x80, 0x05, 0x38, 0x44, 0x04, 0x08, 0x10, 0x10, 0x80, 0x0A, 0x0C, 0x02, 0x1C, 0x02, 0xE0, 0x10, 0x11, 0x61, 0x81, 0x41, 0x3E, 0x80, 0x02, 0x80, 0x7E, 0x01, 0x80, 0x02, 0x0C, 0x1E, 0x0C, 0x80, 0x08, 0x08, 0x04, 0x02, 0x0C, 0x08, 0x04, 0x42, 0x3E, 0x1C, 0x80, 0x08, 0x08, 0x1C, 0x34, 0x22, 0x42, 0x41, 0x41, 0x7F, 0x3E, 0x80, 0x08, 0x01, 0x1F, 0x1E, 0x10, 0x10, 0x10, 0x30, 0x70, 0x60, 0x80, 0x09, 0x06, 0x89, 0x49, 0x26, 0x10, 0x08, 0x64, 0x92, 0x91, 0x60, 0x80, 0x05, 0x18, 0x18, 0x0C, 0x0C, 0x06, 0x06, 0x80, 0x04, 0x08, 0x1C, 0x18, 0x08, 0x04, 0x80, 0x03, 0xE0, 0x10, 0xE0, 0x10, 0x80, 0x08, 0xC0, 0x20, 0xC0, 0x28, 0x08, 0x08, 0x08, 0x08, 0x08, 0x80, 0x07, 0x28, 0x02, 0x81, 0x81, 0x7E, 0x10, 0x28, 0x10, 0x80, 0x0C, 0x60, 0x10, 0x60, 0x10, 0x0E, 0xF1, 0x0C, 0x02, 0x01, 0x01, 0x01, 0x82, 0x7C, 0x80, 0x07, 0x10, 0x20, 0x40, 0x42, 0x3C, 0x10, 0x28, 0x10, 0x80, 0x06, 0x20, 0x40, 0x40, 0x20, 0x38, 0x56, 0x20, 0x80, 0x05, 0x20, 0x40, 0x40, 0x20, 0x18, 0x46, 0x80, 0x05, 0x20, 0x40, 0x48, 0x20, 0x18, 0x46, 0x80, 0x05, 0x80, 0xA8, 0x11, 0x11, 0x51, 0x0E, 0x80, 0x06, 0x60, 0x90, 0x8C, 0x79, 0x11, 0x09, 0xA6, 0x80, 0x06, 0x54, 0x04, 0x04, 0x34, 0x4C, 0x45, 0x3E, 0x80, 0x06, 0x18, 0x04, 0x02, 0x7C, 0x80, 0x81, 0x7E, 0x80, 0x07, 0x80, 0x40, 0xA0, 0xD0, 0x12, 0x21, 0x41, 0x3E, 0x80, 0x08, 0x20, 0x90, 0x48, 0xA0, 0xD0, 0x12, 0x21, 0x41, 0x3E, 0x80, 0x08, 0x22, 0x90, 0x45, 0x20, 0x10, 0x22, 0x41, 0x41, 0x3E, 0x80, 0x0A, 0x28, 0x10, 0x40, 0x40, 0x40, 0x40, 0x42, 0x41, 0x41, 0x21, 0x1E, 0x80, 0x0A, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x41, 0x41, 0x21, 0x1E, 0x80, 0x0A, 0x08, 0x40, 0x54, 0x40, 0x40, 0x40, 0x42, 0x41, 0x41, 0x21, 0x1E, 0x80, 0x08, 0x82, 0x81, 0x81, 0x81, 0x42, 0x3C, 0x10, 0x28, 0x10, 0x80, 0x06, 0x08, 0x1C, 0x32, 0x4A, 0x4C, 0x3C, 0x02, 0x80, 0x03, 0x1C, 0x02, 0x1C, 0x02, 0x80, 0x06, 0x30, 0x48, 0x70, 0x48, 0x34, 0x18, 0x06, 0x80, 0x07, 0x04, 0xE2, 0x11, 0x10, 0x61, 0x81, 0x81, 0x7E, 0x80, 0x08, 0x0A, 0x04, 0xE0, 0x10, 0x11, 0x61, 0x81, 0x81, 0x7E, 0x80, 0x08, 0x06, 0x01, 0x06, 0x01, 0x10, 0x28, 0x06, 0x01, 0x7F, 0x80, 0x06, 0x02, 0x02, 0xC2, 0xAA, 0x7E, 0x01, 0x3E, 0x80, 0x06, 0x54, 0x04, 0x64, 0x54, 0x3E, 0x01, 0x3E, 0x80, 0x03, 0x30, 0x70, 0x38, 0x06, 0x80, 0x04, 0x28, 0x28, 0x10, 0x28, 0x18, 0x80, 0x05, 0x18, 0x34, 0x08, 0x14, 0x44, 0x38, 0x80, 0x0D, 0x5A, 0xA5, 0x66, 0xDA, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x5A, 0x66, 0xA5, 0x5A, 0x80, 0x0B, 0x18, 0x66, 0x42, 0x42, 0x81, 0x99, 0x99, 0x81, 0x42, 0x42, 0x66, 0x18, 0x80, 0x02, 0x10, 0x38, 0x10, 0x80, 0x03, 0x18, 0x64, 0x10, 0x0E, 0x80, 0x01, 0x4C, 0x34, 0x80, 0x05, 0x10, 0x28, 0x30, 0x20, 0x10, 0x0C, 0x80, 0x03, 0x10, 0x44, 0x44, 0x38, 0x80, 0x0D, 0x08, 0x14, 0x2A, 0x55, 0x49, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x41, 0x7F, 0x80, 0x03, 0x1C, 0x22, 0x22, 0x1C, 0x80, 0x08, 0x72, 0x0F, 0x7F, 0x3E, 0x0C, 0x0C, 0x08, 0x08, 0x08, 0x80, 0x08, 0x0C, 0x1C, 0x34, 0x22, 0x42, 0x41, 0x49, 0x7F, 0x36, 0x80, 0x08, 0x18, 0x3C, 0x06, 0x7E, 0x3C, 0x0C, 0x06, 0x02, 0x01, 0x80, 0x05, 0x80, 0xA8, 0x11, 0x11, 0x11, 0x4E, 0x80, 0x06, 0x60, 0x90, 0x8C, 0x79, 0x11, 0x11, 0x4E, 0x80, 0x09, 0x0E, 0x01, 0x31, 0x0E, 0x02, 0x01, 0x11, 0x01, 0x82, 0x7C, 0x80, 0x03, 0x28, 0x28, 0x28, 0x28, 0x80, 0x09, 0x30, 0x48, 0x48, 0x3C, 0x02, 0x2A, 0x2A, 0x2A, 0x2A, 0x02, 0x80, 0x09, 0x36, 0x49, 0x49, 0x49, 0x49, 0x49, 0x32, 0x0C, 0x32, 0x40, 0x80, 0x06, 0x36, 0x49, 0x49, 0x49, 0x49, 0x49, 0x26, 0x80, 0x09, 0x2A, 0x55, 0x55, 0x55, 0x41, 0x41, 0x02, 0x0C, 0x32, 0x40, 0x80, 0x06, 0x36, 0x49, 0x49, 0x49, 0x41, 0x41, 0x22, 0x80, 0x09, 0x36, 0x49, 0x49, 0x49, 0x41, 0x41, 0x02, 0x0C, 0x32, 0x40, 0x80, 0x08, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x66, 0x3F, 0x80, 0x0A, 0x30, 0x37, 0x06, 0x06, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x80, 0x0B, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3C, 0x18, 0x30, 0x1C, 0x80, 0x08, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x80, 0x0B, 0x06, 0x06, 0x30, 0x30, 0x30, 0x3C, 0x36, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x0C, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x0C, 0x18, 0x0E, 0x80, 0x0C, 0x38, 0x30, 0x30, 0x3C, 0x36, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x0C, 0x18, 0x0E, 0x80, 0x0C, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x08, 0x1C, 0x36, 0x80, 0x0C, 0x38, 0x30, 0x30, 0x3C, 0x36, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x08, 0x1C, 0x36, 0x80, 0x0C, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x46, 0x66, 0x7F, 0x08, 0x1C, 0x36, 0x80, 0x09, 0x3E, 0x63, 0x7F, 0x03, 0x03, 0x63, 0x3E, 0x08, 0x1C, 0x36, 0x80, 0x0B, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x66, 0x7F, 0x18, 0x30, 0x1C, 0x80, 0x08, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x06, 0x0F, 0x80, 0x08, 0x1C, 0x36, 0x26, 0x0F, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x0B, 0x30, 0x30, 0x07, 0x06, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x67, 0x80, 0x08, 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x67, 0x80, 0x0C, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x06, 0x0C, 0x07, 0x80, 0x0C, 0x07, 0x06, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x67, 0x0C, 0x18, 0x0E, 0x80, 0x02, 0x30, 0x18, 0x66, 0x80, 0x07, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x03, 0x30, 0x18, 0x66, 0x66, 0x80, 0x0A, 0x30, 0x37, 0x06, 0x06, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x67, 0x80, 0x0C, 0x0F, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x08, 0x1C, 0x36, 0x80, 0x0C, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x08, 0x1C, 0x36, 0x80, 0x0C, 0x63, 0x67, 0x6F, 0x7F, 0x7B, 0x73, 0x63, 0x63, 0x63, 0x63, 0x08, 0x1C, 0x36, 0x80, 0x09, 0x3B, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x08, 0x1C, 0x36, 0x80, 0x0B, 0x30, 0x18, 0x4E, 0x39, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x02, 0x06, 0x0C, 0x3E, 0x80, 0x02, 0x30, 0x18, 0x3E, 0x80, 0x02, 0x06, 0x36, 0x18, 0x80, 0x07, 0x3E, 0x63, 0x63, 0x0E, 0x38, 0x63, 0x63, 0x3E, 0x80, 0x03, 0x06, 0x06, 0x30, 0x18, 0x80, 0x0B, 0x0C, 0x22, 0x1C, 0x08, 0x3E, 0x63, 0x63, 0x0E, 0x38, 0x63, 0x63, 0x3E, 0x80, 0x0B, 0x0C, 0x0C, 0x22, 0x1C, 0x08, 0x3E, 0x63, 0x06, 0x1C, 0x30, 0x63, 0x3E, 0x80, 0x08, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x0A, 0x60, 0x68, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x80, 0x0C, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x08, 0x1C, 0x36, 0x80, 0x0C, 0x08, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x10, 0x38, 0x6C, 0x80, 0x0C, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x08, 0x1C, 0x36, 0x80, 0x09, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x08, 0x1C, 0x36, 0x80, 0x03, 0x30, 0x18, 0x4E, 0x39, 0x80, 0x06, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x08, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x08, 0x80, 0x0B, 0x08, 0x1C, 0x22, 0x7F, 0x63, 0x31, 0x18, 0x0C, 0x06, 0x43, 0x63, 0x7F, 0x80, 0x08, 0x08, 0x0C, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x80, 0x08, 0x1C, 0x36, 0x26, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x80, 0x0B, 0x1C, 0x30, 0x18, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x80, 0x0B, 0xC0, 0x68, 0x1C, 0x36, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x80, 0x03, 0xC0, 0x68, 0x1C, 0x36, 0x80, 0x0B, 0x03, 0x16, 0x38, 0x6C, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x80, 0x03, 0x03, 0x16, 0x38, 0x6C, 0x80, 0x0B, 0x70, 0xC8, 0x5C, 0x36, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x80, 0x0B, 0x6E, 0x3B, 0x08, 0x14, 0x2A, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x80, 0x0B, 0x6E, 0x3B, 0x08, 0x1C, 0x22, 0x1E, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x0B, 0x30, 0x18, 0x22, 0x1C, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x80, 0x03, 0x30, 0x18, 0x22, 0x1C, 0x80, 0x0B, 0x06, 0x0C, 0x22, 0x1C, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x80, 0x03, 0x06, 0x0C, 0x22, 0x1C, 0x80, 0x0B, 0x0C, 0x10, 0x2A, 0x1C, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x80, 0x03, 0x0C, 0x10, 0x2A, 0x1C, 0x80, 0x0B, 0x4E, 0x39, 0x22, 0x1C, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x80, 0x03, 0x4E, 0x39, 0x22, 0x1C, 0x80, 0x0B, 0x1C, 0x30, 0x18, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x66, 0x7F, 0x80, 0x0B, 0xC4, 0x6E, 0x11, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x66, 0x7F, 0x80, 0x0B, 0x23, 0x76, 0x88, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x66, 0x7F, 0x80, 0x0B, 0x6E, 0x3B, 0x08, 0x1C, 0x22, 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x80, 0x0B, 0x6E, 0x3B, 0x08, 0x1C, 0x22, 0x3E, 0x63, 0x7F, 0x03, 0x03, 0x63, 0x3E, 0x80, 0x0B, 0x1C, 0x30, 0x18, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x0B, 0x1C, 0x30, 0x18, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x0B, 0xC4, 0x6E, 0x11, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x0B, 0x23, 0x76, 0x88, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x0B, 0x70, 0xC8, 0x5C, 0x22, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x0B, 0x6E, 0x3B, 0x08, 0x14, 0x22, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x0B, 0x6E, 0x3B, 0x08, 0x1C, 0x22, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x0B, 0x18, 0xCC, 0xC0, 0x5E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x09, 0xD8, 0xCC, 0x60, 0x1E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x0B, 0x06, 0xCC, 0xC0, 0x5E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x09, 0xC6, 0xCC, 0x60, 0x1E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x0B, 0x0E, 0xD8, 0xCC, 0x5E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x0A, 0x0E, 0xD8, 0xCC, 0x60, 0x1E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x0B, 0x16, 0xCD, 0xC0, 0x5E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x0A, 0x16, 0xCD, 0xC0, 0x60, 0x1E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x0B, 0x1C, 0x30, 0x18, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x80, 0x0B, 0x18, 0xCC, 0xC0, 0x73, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x09, 0xD8, 0xCC, 0x60, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x0B, 0x06, 0xCC, 0xC0, 0x73, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x09, 0xC6, 0xCC, 0x60, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x0B, 0x0E, 0xD8, 0xCC, 0x73, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x0A, 0x0E, 0xD8, 0xCC, 0x60, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x0B, 0x16, 0xCD, 0xC0, 0x73, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x0A, 0x16, 0xCD, 0xC0, 0x60, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x80, 0x09, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7E, 0x30, 0x18, 0x6F, 0x60, 0x80, 0x0B, 0x1C, 0x30, 0x18, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x01, 0x5C, 0x3A, 0x80, 0x02, 0x06, 0x36, 0x63, 0x80, 0x02, 0x03, 0x33, 0x66, 0x80, 0x02, 0x06, 0x66, 0x33, 0x80, 0x02, 0x03, 0x63, 0x36, 0x80, 0x03, 0x2C, 0x1A, 0x30, 0x18, 0x80, 0x03, 0x2C, 0x1A, 0x0C, 0x18, 0x80, 0x04, 0x25, 0x55, 0x57, 0x57, 0x65, 0x80, 0x04, 0x25, 0x57, 0x55, 0x55, 0x65, 0x80, 0x04, 0x57, 0x51, 0x73, 0x71, 0x57, 0x80, 0x04, 0x57, 0x71, 0x53, 0x51, 0x57, 0x80, 0x04, 0x53, 0x74, 0x52, 0x54, 0x53, 0x80, 0x04, 0x55, 0x75, 0x57, 0x54, 0x54, 0x80, 0x04, 0x56, 0x71, 0x53, 0x55, 0x52, 0x80, 0x04, 0x1C, 0x04, 0x0C, 0x04, 0x04, 0x80, 0x04, 0x0C, 0x14, 0x0C, 0x04, 0x04, 0x80, 0x04, 0x57, 0x52, 0x72, 0x52, 0x52, 0x80, 0x04, 0x14, 0x14, 0x1C, 0x14, 0x14, 0x80, 0x04, 0x45, 0x45, 0x47, 0x57, 0x25, 0x80, 0x04, 0x10, 0x10, 0x10, 0x14, 0x08, 0x80, 0x0A, 0x01, 0x01, 0x01, 0x0F, 0x14, 0x0C, 0x14, 0x50, 0x70, 0x70, 0x50, 0x80, 0x0A, 0x03, 0x05, 0x03, 0x05, 0x04, 0x04, 0x1C, 0x50, 0x70, 0x70, 0x50, 0x80, 0x04, 0x39, 0x4B, 0x3D, 0x49, 0x39, 0x80, 0x03, 0x18, 0x0C, 0x0C, 0x0C, 0x80, 0x03, 0x0C, 0x0C, 0x0C, 0x18, 0x80, 0x03, 0x66, 0x33, 0x33, 0x33, 0x80, 0x03, 0x33, 0x33, 0x33, 0x66, 0x80, 0x09, 0x18, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x06, 0x04, 0x0C, 0x1C, 0x3C, 0x1C, 0x0C, 0x04, 0x80, 0x08, 0x03, 0x63, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x6C, 0x6C, 0x80, 0x08, 0x03, 0x63, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xD6, 0xD6, 0x80, 0x02, 0x18, 0x18, 0x08, 0x80, 0x02, 0x36, 0x36, 0x12, 0x80, 0x02, 0xDB, 0xDB, 0x49, 0x80, 0x02, 0x18, 0x18, 0x10, 0x80, 0x02, 0x36, 0x36, 0x24, 0x80, 0x02, 0xDB, 0xDB, 0x92, 0x80, 0x06, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x80, 0x06, 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x80, 0x06, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x80, 0x06, 0x7E, 0xC3, 0xDB, 0xD8, 0x78, 0x38, 0x18, 0x80, 0x01, 0x41, 0x3E, 0x80, 0x01, 0x3E, 0x41, 0x80, 0x04, 0x60, 0x30, 0x18, 0x1C, 0x36, 0x80, 0x02, 0x08, 0x1C, 0x14, 0x80, 0x02, 0x22, 0x77, 0x55, 0x80, 0x01, 0x3C, 0x3C, 0x80, 0x09, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0C, 0x0C, 0x06, 0x06, 0x80, 0x09, 0x3C, 0x0C, 0x0C, 0x0C, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x80, 0x09, 0x3C, 0x30, 0x30, 0x30, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x80, 0x06, 0xDE, 0xF3, 0xF3, 0xD8, 0xCC, 0xCC, 0xCC, 0x80, 0x01, 0xCC, 0xCC, 0x80, 0x06, 0x7B, 0xCF, 0xCF, 0x63, 0x33, 0x33, 0x33, 0x80, 0x05, 0x7E, 0x7E, 0x60, 0x60, 0x30, 0x30, 0x80, 0x09, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x80, 0x06, 0x7C, 0x4E, 0x4F, 0x4F, 0x4F, 0x4E, 0x7C, 0x80, 0x06, 0x1F, 0x39, 0x79, 0x79, 0x79, 0x39, 0x1F, 0x80, 0x09, 0x1E, 0x33, 0x03, 0xF3, 0x33, 0x33, 0xFE, 0x30, 0x30, 0xF0, 0x80, 0x0D, 0x20, 0x20, 0x3E, 0x73, 0x13, 0x13, 0x0B, 0x0B, 0x0B, 0x07, 0x67, 0x3E, 0x02, 0x02, 0x80, 0x09, 0x3E, 0x63, 0x03, 0x03, 0x6B, 0x1B, 0x1B, 0x1B, 0x7B, 0x3E, 0x80, 0x09, 0x1F, 0x03, 0x03, 0x03, 0x0F, 0xB3, 0x73, 0x33, 0x33, 0x33, 0x80, 0x09, 0x1C, 0x36, 0x06, 0x1F, 0x06, 0x1F, 0x06, 0x06, 0x67, 0x3F, 0x80, 0x08, 0x40, 0x37, 0x6B, 0x7B, 0x6B, 0x6B, 0x6F, 0x6B, 0x02, 0x80, 0x09, 0x66, 0x66, 0x6E, 0xFF, 0x6E, 0x76, 0xFF, 0x76, 0x66, 0x66, 0x80, 0x09, 0x3F, 0x66, 0x66, 0x3E, 0x46, 0x66, 0xF6, 0x66, 0x66, 0xCF, 0x80, 0x09, 0x1F, 0x33, 0x33, 0x33, 0x1F, 0x07, 0xCF, 0x6B, 0xDB, 0x73, 0x80, 0x09, 0x81, 0x81, 0x81, 0x5A, 0xFF, 0x5A, 0xFF, 0x24, 0x24, 0x24, 0x80, 0x07, 0x4F, 0x51, 0x55, 0x55, 0x55, 0x55, 0x45, 0x3D, 0x80, 0x09, 0x38, 0x6C, 0x06, 0x3F, 0x06, 0x1F, 0x06, 0x06, 0x6C, 0x38, 0x80, 0x09, 0x67, 0x66, 0x36, 0x1E, 0x7F, 0x1E, 0x36, 0x66, 0x66, 0x67, 0x80, 0x09, 0x7E, 0x7E, 0x5A, 0x18, 0x78, 0x1E, 0x78, 0x1E, 0x18, 0x3C, 0x80, 0x0A, 0x08, 0x3E, 0x6D, 0x6C, 0xCC, 0xCC, 0xCC, 0xC6, 0x66, 0x6F, 0x3B, 0x80, 0x0B, 0x0E, 0x0B, 0x4B, 0x6B, 0x3E, 0x18, 0x0C, 0x76, 0x1B, 0x19, 0x18, 0x70, 0x80, 0x0B, 0x0E, 0x0B, 0x4B, 0x6B, 0x3E, 0x18, 0x0C, 0x76, 0x1B, 0x31, 0x60, 0x38, 0x80, 0x09, 0x3C, 0x46, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x46, 0x3C, 0x80, 0x09, 0x72, 0x9D, 0x1A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x98, 0x70, 0x80, 0x09, 0x3C, 0x18, 0x3E, 0x5B, 0x1B, 0x1B, 0x5B, 0x3E, 0x98, 0xFC, 0x80, 0x0B, 0x0E, 0x03, 0x43, 0x63, 0x3E, 0x18, 0x0C, 0x76, 0xDB, 0xD9, 0xD8, 0x70, 0x80, 0x0B, 0x0E, 0x03, 0x43, 0x63, 0x3E, 0x18, 0x0C, 0xDE, 0xDB, 0xD9, 0xD8, 0xB0, 0x80, 0x09, 0x1E, 0x33, 0x61, 0x64, 0x7C, 0x64, 0x60, 0x61, 0x33, 0x1E, 0x80, 0x09, 0xFE, 0x9D, 0x1A, 0x58, 0x78, 0x58, 0x18, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x58, 0x66, 0x62, 0xE1, 0x31, 0x31, 0x3E, 0x19, 0x19, 0x0E, 0x80, 0x09, 0x4A, 0xAD, 0xA8, 0x68, 0x34, 0x2C, 0x16, 0x95, 0x55, 0x32, 0x80, 0x0C, 0x12, 0x0D, 0x01, 0x12, 0x3E, 0x66, 0x64, 0x64, 0x65, 0x62, 0x60, 0x2C, 0x12, 0x80, 0x09, 0x47, 0x45, 0x45, 0x45, 0x7D, 0x45, 0x45, 0x45, 0x45, 0x47, 0x80, 0x09, 0x1C, 0x18, 0x18, 0x6C, 0xDC, 0xDC, 0xCC, 0x66, 0x66, 0x67, 0x80, 0x09, 0x1C, 0x78, 0x18, 0x6E, 0xDC, 0xDC, 0xCC, 0x66, 0x66, 0x67, 0x80, 0x09, 0xCC, 0x72, 0x60, 0x60, 0x30, 0x30, 0xF8, 0x36, 0x11, 0x0E, 0x80, 0x09, 0x8E, 0x71, 0x20, 0x30, 0x60, 0xC0, 0xC6, 0xC3, 0x42, 0x3C, 0x80, 0x09, 0x62, 0x92, 0x9C, 0x78, 0x18, 0x0C, 0x0E, 0x8D, 0x5D, 0x36, 0x80, 0x09, 0x70, 0x98, 0x8C, 0x4C, 0x26, 0x16, 0x0E, 0x87, 0x66, 0x1C, 0x80, 0x09, 0x1B, 0xFF, 0x1B, 0x7B, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7B, 0x80, 0x09, 0x47, 0x45, 0x4D, 0x4D, 0x55, 0x55, 0x65, 0x65, 0x45, 0x47, 0x80, 0x09, 0x33, 0xF3, 0xB7, 0xFF, 0x3F, 0xFB, 0x33, 0x33, 0x33, 0x33, 0x80, 0x09, 0x3C, 0x42, 0x9D, 0xA5, 0xA5, 0x9D, 0x85, 0x85, 0x42, 0x3C, 0x80, 0x0A, 0x02, 0x71, 0xC9, 0xC5, 0xC6, 0xD2, 0x56, 0x25, 0x0D, 0x0D, 0x06, 0x80, 0x09, 0x3F, 0x45, 0x45, 0x45, 0x45, 0x3D, 0x05, 0x05, 0x05, 0x07, 0x80, 0x0A, 0x3E, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x55, 0x65, 0x7E, 0x80, 0x80, 0x09, 0x7C, 0xB2, 0xB2, 0x98, 0x78, 0x38, 0x2C, 0x2C, 0xAD, 0x46, 0x80, 0x09, 0x1A, 0x65, 0xC5, 0x36, 0x1D, 0x64, 0x64, 0x64, 0xE5, 0x43, 0x80, 0x09, 0x3F, 0x45, 0x45, 0x45, 0x45, 0x3D, 0x0D, 0x15, 0x25, 0x47, 0x80, 0x0A, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x36, 0xB6, 0xE6, 0x66, 0x77, 0x10, 0x80, 0x0C, 0x0C, 0x30, 0x3F, 0x63, 0x63, 0x63, 0x3F, 0x1B, 0x3B, 0x3B, 0x67, 0x67, 0x04, 0x80, 0x03, 0x8E, 0xDB, 0xAC, 0x8B, 0x80, 0x04, 0x7F, 0x4A, 0x5A, 0x4A, 0xFA, 0x80, 0x03, 0x8F, 0xDA, 0xAA, 0x8A, 0x80, 0x0C, 0x06, 0x18, 0x73, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x67, 0x36, 0x1C, 0x0A, 0x02, 0x80, 0x09, 0x7F, 0x50, 0x28, 0x28, 0x14, 0x14, 0x0A, 0x0A, 0x05, 0x7F, 0x80, 0x0C, 0x7F, 0x39, 0x0C, 0x7F, 0x30, 0x18, 0x1C, 0x30, 0x60, 0x60, 0x63, 0x63, 0x3E, 0x80, 0x09, 0x18, 0x64, 0xC0, 0xC8, 0x30, 0xC8, 0xC0, 0xC0, 0x66, 0x19, 0x80, 0x06, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x38, 0x18, 0x80, 0x0B, 0x1C, 0x36, 0x1C, 0x08, 0x1C, 0x1C, 0x36, 0x36, 0x63, 0x7F, 0x63, 0x63, 0x80, 0x09, 0x78, 0xB4, 0xB4, 0x58, 0x78, 0xD8, 0x8C, 0x8C, 0x4D, 0x36, 0x80, 0x09, 0x28, 0xD6, 0x13, 0x33, 0x63, 0x63, 0x33, 0x03, 0xC6, 0x38, 0x80, 0x06, 0x3C, 0x66, 0xE7, 0xFF, 0x07, 0xE6, 0x7C, 0x80, 0x06, 0x38, 0x64, 0x22, 0x1F, 0x03, 0x13, 0x0E, 0x80, 0x09, 0x32, 0x4A, 0x3C, 0x08, 0x3C, 0x06, 0x03, 0xC3, 0x33, 0x1E, 0x80, 0x09, 0xCE, 0x73, 0x18, 0x5C, 0x3A, 0x18, 0x0C, 0x0C, 0x0D, 0x06, 0x80, 0x09, 0x78, 0x30, 0x30, 0x30, 0x34, 0x3C, 0x34, 0x31, 0x33, 0x7F, 0x80, 0x09, 0x48, 0x48, 0x48, 0x68, 0x6C, 0x7C, 0x5C, 0x5A, 0x4A, 0x89, 0x80, 0x06, 0x38, 0x64, 0x62, 0x63, 0x23, 0x13, 0x0E, 0x80, 0x09, 0x42, 0x63, 0xE7, 0x5E, 0x1C, 0x3A, 0x73, 0xE7, 0xC6, 0x47, 0x80, 0x09, 0x01, 0x3F, 0x7E, 0x60, 0x60, 0x60, 0x60, 0x30, 0x7E, 0x7F, 0x80, 0x09, 0x02, 0x1E, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x78, 0x7E, 0x4F, 0x80, 0x09, 0x01, 0x7F, 0x7E, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x18, 0x80, 0x01, 0x1C, 0x1C, 0x80, 0x06, 0x1E, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3E, 0x80, 0x06, 0xBE, 0xFF, 0xC1, 0x61, 0x41, 0x7F, 0x3E, 0x80, 0x0C, 0x03, 0x03, 0x43, 0x63, 0x33, 0x18, 0x0C, 0x06, 0x3B, 0x61, 0x38, 0x60, 0x38, 0x80, 0x0C, 0x07, 0x0C, 0x46, 0x63, 0x3F, 0x18, 0x0C, 0x06, 0x3B, 0x61, 0x38, 0x60, 0x38, 0x80, 0x0C, 0x03, 0x03, 0x43, 0x63, 0x33, 0x18, 0x0C, 0x06, 0x7B, 0x19, 0x38, 0x60, 0x38, 0x80, 0x0C, 0x07, 0x0C, 0x46, 0x63, 0x3F, 0x18, 0x0C, 0x06, 0x7B, 0x19, 0x38, 0x60, 0x38, 0x80, 0x0C, 0x07, 0x0C, 0x46, 0x6C, 0x37, 0x18, 0x0C, 0x06, 0x7B, 0x19, 0x38, 0x60, 0x38, 0x80, 0x0C, 0x0C, 0x0E, 0x4D, 0x6F, 0x3C, 0x18, 0x0C, 0x06, 0x7B, 0x19, 0x38, 0x60, 0x38, 0x80, 0x0C, 0x03, 0x03, 0x43, 0x63, 0x33, 0x18, 0x0C, 0x06, 0x3B, 0x0D, 0x3C, 0x6C, 0x38, 0x80, 0x0C, 0x0F, 0x03, 0x47, 0x6C, 0x37, 0x18, 0x0C, 0x06, 0x3B, 0x0D, 0x3C, 0x6C, 0x38, 0x80, 0x0C, 0x03, 0x03, 0x43, 0x63, 0x33, 0x18, 0x0C, 0x06, 0x3B, 0x6D, 0x38, 0x6C, 0x38, 0x80, 0x0C, 0x07, 0x0C, 0x46, 0x6C, 0x37, 0x18, 0x0C, 0x06, 0x3B, 0x6D, 0x38, 0x6C, 0x38, 0x80, 0x0C, 0x0F, 0x01, 0x47, 0x6C, 0x37, 0x18, 0x0C, 0x06, 0x3B, 0x6D, 0x38, 0x6C, 0x38, 0x80, 0x0C, 0x0F, 0x0C, 0x46, 0x66, 0x36, 0x18, 0x0C, 0x06, 0x3B, 0x6D, 0x38, 0x6C, 0x38, 0x80, 0x09, 0x03, 0x03, 0x43, 0x63, 0x33, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0x09, 0x7F, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x7F, 0x80, 0x09, 0xFF, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xFF, 0x80, 0x09, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x73, 0x73, 0x23, 0x80, 0x09, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0xCE, 0xC4, 0x80, 0x09, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA6, 0xA6, 0xA6, 0x80, 0x09, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAA, 0xAA, 0xAA, 0xAA, 0x80, 0x09, 0xDB, 0xDB, 0xDB, 0x73, 0x73, 0x73, 0xDB, 0xDB, 0xDB, 0xDB, 0x80, 0x09, 0xDB, 0xDB, 0xDB, 0xCE, 0xCE, 0xCE, 0xDB, 0xDB, 0xDB, 0xDB, 0x80, 0x09, 0xA9, 0xA9, 0xA9, 0xA6, 0xA6, 0xA6, 0xA9, 0xA9, 0xA9, 0xA9, 0x80, 0x06, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x80, 0x06, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x80, 0x06, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x73, 0x23, 0x80, 0x06, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0xC4, 0x80, 0x06, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA6, 0xA6, 0x80, 0x01, 0xA8, 0xA8, 0x80, 0x06, 0xAD, 0xAD, 0xAD, 0xAD, 0xAA, 0xAA, 0xAA, 0x80, 0x06, 0xDB, 0xDB, 0x73, 0x73, 0x73, 0xDB, 0xDB, 0x80, 0x06, 0xDB, 0xDB, 0xCE, 0xCE, 0xCE, 0xDB, 0xDB, 0x80, 0x06, 0xA9, 0xA9, 0xA6, 0xA6, 0xA9, 0xA9, 0xA9, 0x80, 0x09, 0x3C, 0x5A, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x5A, 0x3C, 0x80, 0x09, 0x1F, 0x33, 0x67, 0x6B, 0x6B, 0x6B, 0x6B, 0x67, 0x33, 0x1F, 0x80, 0x09, 0x3C, 0x5A, 0x99, 0xBD, 0xDB, 0xDB, 0xBD, 0x99, 0x5A, 0x3C, 0x80, 0x04, 0x0C, 0x06, 0xFF, 0x06, 0x0C, 0x80, 0x09, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x04, 0x30, 0x60, 0xFF, 0x60, 0x30, 0x80, 0x09, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x80, 0x04, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x80, 0x08, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x80, 0x06, 0xF0, 0xE0, 0xB0, 0x18, 0x0C, 0x06, 0x03, 0x80, 0x06, 0x03, 0x06, 0x0C, 0x18, 0xB0, 0xE0, 0xF0, 0x80, 0x06, 0xC0, 0x60, 0x30, 0x18, 0x0D, 0x07, 0x0F, 0x80, 0x04, 0x4C, 0x46, 0xFF, 0x26, 0x2C, 0x80, 0x04, 0x34, 0x64, 0xFF, 0x62, 0x32, 0x80, 0x02, 0x07, 0x73, 0xDD, 0x80, 0x02, 0xE0, 0xCE, 0xBB, 0x80, 0x04, 0x6C, 0x36, 0xFF, 0x36, 0x6C, 0x80, 0x09, 0x18, 0x3C, 0x7E, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x80, 0x04, 0x36, 0x6C, 0xFF, 0x6C, 0x36, 0x80, 0x09, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x3C, 0x18, 0x80, 0x04, 0xCC, 0x66, 0x3F, 0x66, 0xCC, 0x80, 0x04, 0x33, 0x66, 0xFC, 0x66, 0x33, 0x80, 0x04, 0xCC, 0xC6, 0xFF, 0xC6, 0xCC, 0x80, 0x09, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x80, 0x04, 0x33, 0x63, 0xFF, 0x63, 0x33, 0x80, 0x09, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x80, 0x09, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x80, 0x05, 0x60, 0xCC, 0xC6, 0x7F, 0x06, 0x0C, 0x80, 0x05, 0x06, 0x33, 0x63, 0xFE, 0x60, 0x30, 0x80, 0x05, 0x60, 0xDC, 0xD6, 0x7F, 0x16, 0x0C, 0x80, 0x05, 0x06, 0x3B, 0x6B, 0xFE, 0x68, 0x30, 0x80, 0x04, 0x24, 0x5A, 0xFF, 0x66, 0x24, 0x80, 0x04, 0x34, 0x76, 0xFF, 0x6E, 0x2C, 0x80, 0x09, 0x0C, 0x0C, 0x06, 0xC6, 0xFF, 0x63, 0x68, 0x38, 0x38, 0x78, 0x80, 0x08, 0x0C, 0x06, 0x7F, 0x66, 0x6C, 0x60, 0x60, 0x60, 0x60, 0x80, 0x08, 0x18, 0x30, 0x7F, 0x33, 0x1B, 0x03, 0x03, 0x03, 0x03, 0x80, 0x08, 0x60, 0x60, 0x60, 0x60, 0x6C, 0x66, 0x7F, 0x06, 0x0C, 0x80, 0x08, 0x03, 0x03, 0x03, 0x03, 0x1B, 0x33, 0x7F, 0x30, 0x18, 0x80, 0x05, 0x3F, 0x30, 0x30, 0xFC, 0x78, 0x30, 0x80, 0x05, 0x60, 0x6C, 0x66, 0x7F, 0x06, 0x0C, 0x80, 0x07, 0x78, 0xCC, 0xCC, 0xCC, 0x0C, 0x3F, 0x1E, 0x0C, 0x80, 0x07, 0x1E, 0x33, 0x33, 0x33, 0x30, 0xFC, 0x78, 0x30, 0x80, 0x09, 0x19, 0x0D, 0xFF, 0x0D, 0x19, 0x98, 0xB0, 0xFF, 0xB0, 0x98, 0x80, 0x08, 0x78, 0x38, 0x68, 0xC0, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, 0x80, 0x08, 0x1E, 0x1C, 0x16, 0x03, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, 0x80, 0x09, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x09, 0x18, 0x1C, 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x09, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18, 0x80, 0x09, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x1C, 0x18, 0x80, 0x09, 0x30, 0x60, 0xFF, 0x60, 0x30, 0x0C, 0x06, 0xFF, 0x06, 0x0C, 0x80, 0x09, 0x24, 0x74, 0xFC, 0x24, 0x24, 0x24, 0x24, 0x3F, 0x2E, 0x24, 0x80, 0x09, 0x0C, 0x06, 0xFF, 0x06, 0x0C, 0x30, 0x60, 0xFF, 0x60, 0x30, 0x80, 0x09, 0x24, 0x7E, 0xFF, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x80, 0x09, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0xFF, 0x7E, 0x24, 0x80, 0x04, 0x44, 0xFE, 0x23, 0xFE, 0x24, 0x80, 0x04, 0x34, 0x7E, 0xD3, 0x7E, 0x2C, 0x80, 0x04, 0x24, 0x7F, 0xC4, 0x7F, 0x22, 0x80, 0x04, 0x04, 0xFE, 0x03, 0xFE, 0x04, 0x80, 0x09, 0x1C, 0x3E, 0x77, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x80, 0x04, 0x20, 0x7F, 0xC0, 0x7F, 0x20, 0x80, 0x09, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x77, 0x3E, 0x1C, 0x80, 0x04, 0x24, 0x7E, 0xC3, 0x7E, 0x24, 0x80, 0x09, 0x1C, 0x3E, 0x77, 0x36, 0x36, 0x36, 0x36, 0x77, 0x3E, 0x1C, 0x80, 0x08, 0x0F, 0x07, 0x0D, 0x1B, 0x37, 0x6D, 0xD8, 0x30, 0x20, 0x80, 0x08, 0xF0, 0xE0, 0xB0, 0xD8, 0xEC, 0xB6, 0x1B, 0x0C, 0x04, 0x80, 0x08, 0x04, 0x0C, 0x1B, 0xB6, 0xEC, 0xD8, 0xB0, 0xE0, 0xF0, 0x80, 0x08, 0x20, 0x30, 0xD8, 0x6D, 0x37, 0x1B, 0x0D, 0x07, 0x0F, 0x80, 0x06, 0x08, 0xFC, 0x06, 0xFF, 0x06, 0xFC, 0x08, 0x80, 0x06, 0x10, 0x3F, 0x60, 0xFF, 0x60, 0x3F, 0x10, 0x80, 0x04, 0x0C, 0x56, 0xFF, 0xA6, 0x0C, 0x80, 0x04, 0x30, 0x65, 0xFF, 0x6A, 0x30, 0x80, 0x09, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x3C, 0x18, 0x3C, 0x18, 0x18, 0x80, 0x09, 0x18, 0x18, 0x3C, 0x18, 0x3C, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x80, 0x04, 0x0C, 0x06, 0xAB, 0x06, 0x0C, 0x80, 0x03, 0x18, 0x3C, 0x66, 0x18, 0x80, 0x04, 0x30, 0x60, 0xD5, 0x60, 0x30, 0x80, 0x03, 0x18, 0x66, 0x3C, 0x18, 0x80, 0x04, 0x19, 0x0D, 0xFF, 0x0D, 0x19, 0x80, 0x04, 0x98, 0xB0, 0xFF, 0xB0, 0x98, 0x80, 0x06, 0x08, 0xFC, 0x82, 0x81, 0x82, 0xFC, 0x08, 0x80, 0x09, 0x08, 0x14, 0x22, 0x63, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3E, 0x80, 0x06, 0x10, 0x3F, 0x41, 0x81, 0x41, 0x3F, 0x10, 0x80, 0x09, 0x3E, 0x22, 0x22, 0x22, 0x22, 0x22, 0x63, 0x22, 0x14, 0x08, 0x80, 0x06, 0x08, 0x14, 0x22, 0x63, 0x22, 0x22, 0x3E, 0x80, 0x02, 0x3E, 0x22, 0x3E, 0x80, 0x09, 0x08, 0x14, 0x22, 0x63, 0x22, 0x22, 0x22, 0x63, 0x41, 0x7F, 0x80, 0x09, 0x08, 0x14, 0x3E, 0x63, 0x22, 0x22, 0x22, 0x63, 0x41, 0x7F, 0x80, 0x09, 0x08, 0x1C, 0x2A, 0x6B, 0x2A, 0x2A, 0x2A, 0x6B, 0x49, 0x7F, 0x80, 0x0A, 0x08, 0x14, 0x2A, 0x77, 0x22, 0x63, 0x22, 0x22, 0x22, 0x22, 0x3E, 0x80, 0x0A, 0x08, 0x14, 0x2A, 0x77, 0x22, 0x63, 0x22, 0x22, 0x63, 0x41, 0x7F, 0x80, 0x06, 0x17, 0x3D, 0x41, 0x81, 0x41, 0x3D, 0x17, 0x80, 0x08, 0xFF, 0x01, 0x3D, 0x1D, 0x35, 0x61, 0xC1, 0x81, 0x01, 0x80, 0x08, 0x80, 0x81, 0x83, 0x86, 0xAC, 0xB8, 0xBC, 0x80, 0xFF, 0x80, 0x0A, 0x08, 0x14, 0x22, 0x63, 0x22, 0x22, 0x22, 0x63, 0x22, 0x14, 0x08, 0x80, 0x09, 0x63, 0x63, 0x7F, 0x63, 0x36, 0x36, 0x1C, 0x1C, 0x08, 0x08, 0x80, 0x08, 0x3C, 0x66, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x3C, 0x80, 0x09, 0x1C, 0x36, 0x60, 0x60, 0x7C, 0x66, 0x63, 0x63, 0x33, 0x1E, 0x80, 0x09, 0x7F, 0x60, 0x60, 0x60, 0x7E, 0x60, 0x60, 0x60, 0x60, 0x7F, 0x80, 0x0B, 0x10, 0x7F, 0x68, 0x68, 0x68, 0x7E, 0x68, 0x64, 0x64, 0x64, 0x7F, 0x02, 0x80, 0x09, 0xC0, 0x7C, 0x66, 0xF3, 0xDB, 0xDB, 0xCF, 0x66, 0x3E, 0x03, 0x80, 0x09, 0x7F, 0x63, 0x63, 0x63, 0x36, 0x36, 0x1C, 0x1C, 0x08, 0x08, 0x80, 0x08, 0x7C, 0x06, 0x03, 0x03, 0x7F, 0x03, 0x03, 0x06, 0x7C, 0x80, 0x0A, 0x20, 0x7C, 0x26, 0x13, 0x13, 0x7F, 0x13, 0x0B, 0x0E, 0x7C, 0x04, 0x80, 0x06, 0x7C, 0x06, 0x03, 0x7F, 0x03, 0x06, 0x7C, 0x80, 0x08, 0x1F, 0x30, 0x60, 0x60, 0x7F, 0x60, 0x60, 0x30, 0x1F, 0x80, 0x0A, 0x10, 0x1F, 0x38, 0x68, 0x64, 0x7F, 0x64, 0x64, 0x32, 0x1F, 0x02, 0x80, 0x06, 0x1F, 0x30, 0x60, 0x7F, 0x60, 0x30, 0x1F, 0x80, 0x06, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x80, 0x0B, 0xFF, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xE7, 0x80, 0x0B, 0xE7, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFF, 0x80, 0x0B, 0xFF, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x18, 0x0C, 0x06, 0x83, 0xFF, 0x80, 0x0B, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0C, 0x0C, 0x06, 0x06, 0x03, 0x03, 0x80, 0x0B, 0x03, 0x03, 0x06, 0x06, 0x0C, 0x0C, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x80, 0x04, 0x24, 0x18, 0x7E, 0x18, 0x24, 0x80, 0x09, 0xC0, 0xC0, 0x60, 0x60, 0x60, 0x30, 0x33, 0x36, 0x1C, 0x18, 0x80, 0x09, 0xC7, 0xCC, 0x66, 0x6C, 0x67, 0x30, 0x33, 0x36, 0x1C, 0x18, 0x80, 0x09, 0xCC, 0xCE, 0x6D, 0x6F, 0x6C, 0x30, 0x33, 0x36, 0x1C, 0x18, 0x80, 0x03, 0x6E, 0x1B, 0x1B, 0x76, 0x80, 0x03, 0x6E, 0xDB, 0xDB, 0x76, 0x80, 0x05, 0x03, 0x03, 0x03, 0x03, 0x03, 0x7F, 0x80, 0x06, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x06, 0xFF, 0x80, 0x07, 0x40, 0x68, 0x30, 0x38, 0x2C, 0x46, 0xFF, 0x40, 0x80, 0x06, 0x08, 0x70, 0x1C, 0x17, 0x1C, 0x70, 0x08, 0x80, 0x09, 0x18, 0x18, 0x18, 0x58, 0x38, 0x1C, 0x1A, 0x18, 0x18, 0x18, 0x80, 0x09, 0x36, 0x36, 0x36, 0x76, 0x3E, 0x37, 0x36, 0x36, 0x36, 0x36, 0x80, 0x07, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x80, 0x0D, 0x30, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1A, 0x0C, 0x80, 0x0D, 0xCC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x33, 0x80, 0x0D, 0x54, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x15, 0x80, 0x0D, 0x30, 0x58, 0x18, 0x18, 0x3C, 0x5A, 0x99, 0x99, 0x5A, 0x3C, 0x18, 0x18, 0x1A, 0x0C, 0x80, 0x0D, 0xCC, 0x66, 0x66, 0x66, 0x7E, 0xE7, 0xE7, 0xE7, 0xE7, 0x7E, 0x66, 0x66, 0x66, 0x33, 0x80, 0x0D, 0x54, 0x2A, 0x2A, 0x2A, 0x3E, 0x6B, 0x6B, 0x6B, 0x6B, 0x3E, 0x2A, 0x2A, 0x2A, 0x15, 0x80, 0x0D, 0x18, 0x2C, 0x0C, 0x0C, 0x1C, 0xAC, 0xCC, 0xEC, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x06, 0x80, 0x0D, 0x30, 0x58, 0x18, 0x18, 0x3C, 0x5A, 0x5F, 0x5A, 0x5A, 0x3C, 0x18, 0x18, 0x1A, 0x0C, 0x80, 0x0D, 0x30, 0x58, 0x18, 0x18, 0x3C, 0x5A, 0xFA, 0x5A, 0x5A, 0x3C, 0x18, 0x18, 0x1A, 0x0C, 0x80, 0x03, 0x4E, 0xDB, 0xDB, 0x72, 0x80, 0x05, 0x0E, 0x1B, 0xDB, 0xDB, 0xD8, 0x70, 0x80, 0x08, 0x38, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x1C, 0x80, 0x07, 0x10, 0x10, 0x08, 0x6E, 0x3B, 0x08, 0x04, 0x04, 0x80, 0x07, 0x10, 0x10, 0x6E, 0x3B, 0x08, 0x7F, 0x04, 0x04, 0x80, 0x06, 0x6E, 0x3B, 0x10, 0x7F, 0x08, 0x7F, 0x04, 0x80, 0x09, 0x10, 0x10, 0x6E, 0x3B, 0x08, 0x7F, 0x04, 0x7F, 0x02, 0x02, 0x80, 0x08, 0x10, 0x10, 0x6E, 0x3B, 0x08, 0x6E, 0x3B, 0x04, 0x04, 0x80, 0x01, 0x63, 0x3E, 0x80, 0x01, 0x3E, 0x63, 0x80, 0x01, 0x03, 0xFB, 0x80, 0x01, 0xFB, 0x03, 0x80, 0x01, 0xC0, 0xDF, 0x80, 0x01, 0xDF, 0xC0, 0x80, 0x02, 0x7F, 0x14, 0x7F, 0x80, 0x02, 0x08, 0x14, 0x08, 0x80, 0x01, 0x1C, 0x22, 0x80, 0x02, 0x08, 0x14, 0x22, 0x80, 0x02, 0x22, 0x14, 0x08, 0x80, 0x03, 0x08, 0x08, 0x3E, 0x14, 0x80, 0x03, 0x08, 0x14, 0x22, 0x3E, 0x80, 0x03, 0x64, 0x3E, 0x2D, 0x36, 0x80, 0x02, 0x16, 0x2A, 0x2A, 0x80, 0x02, 0x0C, 0x10, 0x08, 0x80, 0x01, 0x08, 0x7F, 0x80, 0x07, 0x20, 0x10, 0x7E, 0x10, 0x08, 0x7E, 0x08, 0x04, 0x80, 0x0A, 0x20, 0x10, 0x7F, 0x10, 0x08, 0x7F, 0x08, 0x04, 0x7F, 0x04, 0x02, 0x80, 0x09, 0x70, 0x1C, 0x07, 0x1C, 0x70, 0x10, 0x7F, 0x08, 0x7F, 0x04, 0x80, 0x09, 0x07, 0x1C, 0x70, 0x1C, 0x07, 0x10, 0x7F, 0x08, 0x7F, 0x04, 0x80, 0x06, 0xD8, 0x6C, 0x36, 0x1B, 0x36, 0x6C, 0xD8, 0x80, 0x06, 0x1B, 0x36, 0x6C, 0xD8, 0x6C, 0x36, 0x1B, 0x80, 0x09, 0x66, 0x18, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x66, 0x80, 0x06, 0x10, 0x73, 0x3E, 0x08, 0x3E, 0x67, 0x04, 0x80, 0x08, 0x20, 0x20, 0x70, 0x1C, 0x17, 0x1C, 0x70, 0x08, 0x08, 0x80, 0x08, 0x08, 0x08, 0x07, 0x1C, 0x74, 0x1C, 0x07, 0x02, 0x02, 0x80, 0x09, 0x20, 0x20, 0x70, 0x1C, 0x17, 0x1C, 0x70, 0x08, 0x7F, 0x08, 0x80, 0x09, 0x08, 0x08, 0x07, 0x1C, 0x74, 0x1C, 0x07, 0x02, 0x7F, 0x02, 0x80, 0x0B, 0x20, 0x20, 0x70, 0x1C, 0x17, 0x1C, 0x70, 0x08, 0x6E, 0x3B, 0x04, 0x04, 0x80, 0x0A, 0x08, 0x08, 0x07, 0x1C, 0x74, 0x1C, 0x07, 0x02, 0x6E, 0x3B, 0x01, 0x80, 0x09, 0x70, 0x1C, 0x07, 0x1C, 0x70, 0x07, 0x1C, 0x70, 0x1C, 0x07, 0x80, 0x09, 0x07, 0x1C, 0x70, 0x1C, 0x07, 0x70, 0x1C, 0x07, 0x1C, 0x70, 0x80, 0x0B, 0x10, 0x70, 0x1C, 0x17, 0x1C, 0x78, 0x0F, 0x1C, 0x74, 0x1C, 0x07, 0x04, 0x80, 0x0B, 0x10, 0x17, 0x1C, 0x70, 0x1C, 0x0F, 0x78, 0x1C, 0x07, 0x1C, 0x74, 0x04, 0x80, 0x09, 0x40, 0x60, 0x38, 0x0F, 0x38, 0x60, 0x4F, 0x38, 0x60, 0x40, 0x80, 0x09, 0x01, 0x03, 0x0E, 0x78, 0x0E, 0x03, 0x79, 0x0E, 0x03, 0x01, 0x80, 0x08, 0x20, 0x60, 0x30, 0x1C, 0x17, 0x1C, 0x38, 0x68, 0x08, 0x80, 0x08, 0x08, 0x0B, 0x0E, 0x1C, 0x74, 0x1C, 0x06, 0x03, 0x02, 0x80, 0x07, 0x20, 0x7E, 0x13, 0x13, 0x0B, 0x0B, 0x7E, 0x04, 0x80, 0x07, 0x10, 0x3F, 0x68, 0x68, 0x64, 0x64, 0x3F, 0x02, 0x80, 0x09, 0x20, 0x7E, 0x13, 0x13, 0x0B, 0x0B, 0x7E, 0x04, 0x7F, 0x02, 0x80, 0x09, 0x10, 0x3F, 0x68, 0x68, 0x64, 0x64, 0x3F, 0x02, 0x7F, 0x01, 0x80, 0x08, 0x7E, 0x03, 0x03, 0x03, 0x03, 0x7E, 0x10, 0x7F, 0x08, 0x80, 0x08, 0x3F, 0x60, 0x60, 0x60, 0x60, 0x3F, 0x08, 0x7F, 0x04, 0x80, 0x07, 0x41, 0x49, 0x45, 0x5F, 0x45, 0x49, 0x22, 0x1C, 0x80, 0x07, 0x41, 0x41, 0x49, 0x5D, 0x5D, 0x49, 0x22, 0x1C, 0x80, 0x07, 0x41, 0x41, 0x49, 0x5D, 0x49, 0x41, 0x22, 0x1C, 0x80, 0x07, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x80, 0x07, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x80, 0x06, 0x1C, 0x2A, 0x49, 0x7F, 0x49, 0x2A, 0x1C, 0x80, 0x06, 0x1C, 0x22, 0x41, 0x7F, 0x41, 0x22, 0x1C, 0x80, 0x06, 0x1C, 0x22, 0x55, 0x49, 0x55, 0x22, 0x1C, 0x80, 0x06, 0x1C, 0x22, 0x51, 0x49, 0x45, 0x22, 0x1C, 0x80, 0x06, 0x1C, 0x22, 0x49, 0x5D, 0x49, 0x22, 0x1C, 0x80, 0x06, 0x1C, 0x22, 0x49, 0x55, 0x49, 0x22, 0x1C, 0x80, 0x06, 0x1C, 0x2A, 0x6B, 0x5D, 0x6B, 0x2A, 0x1C, 0x80, 0x06, 0x1C, 0x22, 0x5D, 0x41, 0x5D, 0x22, 0x1C, 0x80, 0x06, 0x1C, 0x22, 0x41, 0x5D, 0x41, 0x22, 0x1C, 0x80, 0x06, 0x7F, 0x49, 0x49, 0x7F, 0x49, 0x49, 0x7F, 0x80, 0x06, 0x7F, 0x41, 0x41, 0x7F, 0x41, 0x41, 0x7F, 0x80, 0x06, 0x7F, 0x63, 0x55, 0x49, 0x55, 0x63, 0x7F, 0x80, 0x06, 0x7F, 0x41, 0x49, 0x5D, 0x49, 0x41, 0x7F, 0x80, 0x08, 0x03, 0x03, 0x03, 0x03, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x80, 0x08, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x09, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x09, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x80, 0x08, 0x06, 0x06, 0x06, 0x06, 0x7E, 0x06, 0x06, 0x06, 0x06, 0x80, 0x08, 0x06, 0x06, 0x06, 0x7E, 0x06, 0x7E, 0x06, 0x06, 0x06, 0x80, 0x08, 0x03, 0x03, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0x03, 0x03, 0x80, 0x08, 0x1B, 0x1B, 0x1B, 0x1B, 0xFB, 0x1B, 0x1B, 0x1B, 0x1B, 0x80, 0x08, 0x15, 0x15, 0x15, 0x15, 0xF5, 0x15, 0x15, 0x15, 0x15, 0x80, 0x08, 0x1B, 0x1B, 0x1B, 0xFB, 0x1B, 0xFB, 0x1B, 0x1B, 0x1B, 0x80, 0x08, 0x03, 0x43, 0x23, 0x23, 0xFF, 0x13, 0x13, 0x0B, 0x03, 0x80, 0x08, 0x03, 0x23, 0x23, 0xFF, 0x13, 0xFF, 0x0B, 0x0B, 0x03, 0x80, 0x08, 0x1B, 0x9B, 0x5B, 0x5B, 0xFB, 0x5B, 0x5B, 0x3B, 0x1B, 0x80, 0x08, 0x1B, 0x9B, 0x5B, 0xFB, 0x5B, 0xFB, 0x5B, 0x3B, 0x1B, 0x80, 0x06, 0x30, 0x60, 0x38, 0x0F, 0x38, 0x60, 0x30, 0x80, 0x06, 0x06, 0x03, 0x0E, 0x78, 0x0E, 0x03, 0x06, 0x80, 0x02, 0x42, 0xFD, 0x42, 0x80, 0x02, 0x42, 0xBF, 0x42, 0x80, 0x02, 0x40, 0xBE, 0x40, 0x80, 0x00, 0x63, 0x80, 0x09, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x07, 0x03, 0x03, 0x03, 0x0F, 0x13, 0x23, 0x23, 0xFF, 0x80, 0x07, 0xC0, 0xE0, 0xD0, 0xC8, 0xC4, 0xC2, 0xC1, 0xFF, 0x80, 0x07, 0x1C, 0x36, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x80, 0x07, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x80, 0x04, 0x08, 0x1C, 0x36, 0x1C, 0x08, 0x80, 0x04, 0x08, 0x08, 0x3E, 0x1C, 0x14, 0x80, 0x06, 0x41, 0x63, 0x55, 0x49, 0x55, 0x63, 0x41, 0x80, 0x06, 0x41, 0x23, 0x15, 0x09, 0x15, 0x23, 0x41, 0x80, 0x06, 0x41, 0x62, 0x54, 0x48, 0x54, 0x62, 0x41, 0x80, 0x06, 0x01, 0x02, 0x04, 0x08, 0x14, 0x22, 0x41, 0x80, 0x06, 0x40, 0x20, 0x10, 0x08, 0x14, 0x22, 0x41, 0x80, 0x07, 0x08, 0x08, 0x08, 0x1C, 0x1C, 0x36, 0x36, 0x63, 0x80, 0x07, 0x63, 0x36, 0x36, 0x1C, 0x1C, 0x08, 0x08, 0x08, 0x80, 0x07, 0x7C, 0x06, 0x73, 0x1B, 0x1B, 0x73, 0x06, 0x7C, 0x80, 0x07, 0x1F, 0x30, 0x67, 0x6C, 0x6C, 0x67, 0x30, 0x1F, 0x80, 0x07, 0x1C, 0x22, 0x49, 0x55, 0x55, 0x55, 0x55, 0x55, 0x80, 0x07, 0x55, 0x55, 0x55, 0x55, 0x55, 0x49, 0x22, 0x1C, 0x80, 0x09, 0x08, 0x08, 0x1C, 0x2A, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x80, 0x06, 0x18, 0x0C, 0x26, 0x73, 0x26, 0x0C, 0x18, 0x80, 0x06, 0x0C, 0x18, 0x32, 0x67, 0x32, 0x18, 0x0C, 0x80, 0x06, 0xA8, 0x54, 0x2A, 0x15, 0x2A, 0x54, 0xA8, 0x80, 0x06, 0x15, 0x2A, 0x54, 0xA8, 0x54, 0x2A, 0x15, 0x80, 0x09, 0x40, 0x60, 0x38, 0x4F, 0x60, 0x38, 0x0F, 0x38, 0x60, 0x40, 0x80, 0x09, 0x01, 0x03, 0x0E, 0x79, 0x03, 0x0E, 0x78, 0x0E, 0x03, 0x01, 0x80, 0x09, 0x50, 0x70, 0x38, 0x0F, 0x38, 0x68, 0x4F, 0x38, 0x64, 0x44, 0x80, 0x09, 0x11, 0x13, 0x0E, 0x78, 0x0E, 0x0B, 0x79, 0x0E, 0x07, 0x05, 0x80, 0x09, 0x20, 0x7F, 0x13, 0x13, 0x0B, 0x0B, 0x7F, 0x04, 0x7F, 0x02, 0x80, 0x09, 0x10, 0x7F, 0x68, 0x68, 0x64, 0x64, 0x7F, 0x02, 0x7F, 0x01, 0x80, 0x08, 0x7F, 0x03, 0x03, 0x03, 0x03, 0x7F, 0x10, 0x7F, 0x08, 0x80, 0x08, 0x7F, 0x60, 0x60, 0x60, 0x60, 0x7F, 0x08, 0x7F, 0x04, 0x80, 0x08, 0x70, 0x1C, 0x07, 0x1C, 0x70, 0x08, 0x6E, 0x3B, 0x08, 0x80, 0x08, 0x07, 0x1C, 0x70, 0x1C, 0x07, 0x08, 0x6E, 0x3B, 0x08, 0x80, 0x0A, 0x40, 0x60, 0x38, 0x0F, 0x38, 0x60, 0x40, 0x08, 0x6E, 0x3B, 0x08, 0x80, 0x0A, 0x01, 0x03, 0x0E, 0x78, 0x0E, 0x03, 0x01, 0x08, 0x6E, 0x3B, 0x08, 0x80, 0x08, 0x10, 0x70, 0x78, 0x6E, 0x6B, 0x6E, 0x78, 0x64, 0x04, 0x80, 0x08, 0x10, 0x13, 0x0F, 0x3B, 0x6B, 0x3B, 0x0F, 0x07, 0x04, 0x80, 0x0A, 0x10, 0x70, 0x78, 0x6E, 0x6B, 0x6E, 0x78, 0x64, 0x04, 0x7F, 0x02, 0x80, 0x0A, 0x10, 0x13, 0x0F, 0x3B, 0x6B, 0x3B, 0x0F, 0x07, 0x04, 0x7F, 0x02, 0x80, 0x07, 0xBC, 0x66, 0xE3, 0xD3, 0xCB, 0xC7, 0x66, 0x3D, 0x80, 0x0D, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0D, 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0B, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x80, 0x0B, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x80, 0x04, 0x7F, 0x03, 0x03, 0x03, 0x03, 0x80, 0x07, 0x42, 0xA5, 0x7E, 0x24, 0x24, 0x7E, 0xA5, 0x42, 0x80, 0x08, 0x1C, 0x1C, 0x2A, 0x51, 0x6F, 0x41, 0x2A, 0x1C, 0x1C, 0x80, 0x0A, 0x7F, 0x7F, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x7F, 0x7F, 0x80, 0x0D, 0x70, 0xD8, 0xD8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0B, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1B, 0x1B, 0x1B, 0x0E, 0x80, 0x0D, 0x30, 0x30, 0x18, 0x18, 0x0C, 0x0C, 0x06, 0x06, 0x0C, 0x0C, 0x18, 0x18, 0x30, 0x30, 0x80, 0x0D, 0x06, 0x06, 0x0C, 0x0C, 0x18, 0x18, 0x30, 0x30, 0x18, 0x18, 0x0C, 0x0C, 0x06, 0x06, 0x80, 0x0E, 0xC0, 0x60, 0x30, 0x30, 0x18, 0x18, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x80, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x18, 0x18, 0x30, 0x30, 0x60, 0xC0, 0x80, 0x0E, 0x03, 0x06, 0x0C, 0x0C, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x80, 0x0D, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x0C, 0x0C, 0x06, 0x03, 0x80, 0x0E, 0xFC, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x80, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xFC, 0x80, 0x0E, 0x3F, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x80, 0x0D, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3F, 0x80, 0x0E, 0xE0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0C, 0x07, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0D, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xE0, 0x80, 0x0E, 0x07, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xE0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0D, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0C, 0x07, 0x80, 0x0F, 0xE0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0C, 0x07, 0x80, 0x0F, 0x07, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xE0, 0x80, 0x0D, 0xFF, 0x83, 0x03, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x18, 0x18, 0x80, 0x0D, 0x18, 0x18, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x03, 0x83, 0xFF, 0x80, 0x0D, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1B, 0x1B, 0x1E, 0x1E, 0x1C, 0x1C, 0x18, 0x18, 0x80, 0x0F, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x09, 0xE0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA4, 0x9E, 0x43, 0x3E, 0x04, 0x80, 0x09, 0x1B, 0x1B, 0x1F, 0x1B, 0x1B, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x80, 0x09, 0x03, 0x03, 0x03, 0x03, 0x0F, 0xF0, 0x30, 0x70, 0x30, 0x30, 0x80, 0x09, 0x1B, 0x1B, 0x1F, 0x0E, 0x04, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x80, 0x09, 0x0F, 0x03, 0x07, 0x03, 0x03, 0xF0, 0x30, 0x70, 0x30, 0x30, 0x80, 0x09, 0x0E, 0x03, 0x03, 0x03, 0x0E, 0x78, 0xD8, 0x78, 0xD8, 0xD8, 0x80, 0x01, 0x41, 0x7F, 0x80, 0x09, 0x19, 0x1B, 0x1F, 0x1B, 0x1B, 0x30, 0x30, 0x30, 0x30, 0xF0, 0x80, 0x06, 0x3E, 0x7F, 0x63, 0x63, 0x06, 0x0C, 0x0C, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x00, 0xB6, 0x80, 0x01, 0xB6, 0xB6, 0x80, 0x04, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x00, 0x55, 0x80, 0x01, 0x55, 0x55, 0x80, 0x08, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0xF8, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0xF8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x08, 0xF8, 0xF8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x08, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0x1F, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0x3F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x08, 0x3F, 0x3F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x07, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x80, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0xF8, 0x80, 0x07, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xF8, 0x80, 0x08, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xF8, 0xF8, 0x80, 0x07, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x80, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x1F, 0x80, 0x07, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x3F, 0x80, 0x08, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x3F, 0x3F, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xF8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xF8, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0xF8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xF8, 0xF8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x3F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x3F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x3F, 0x3F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3F, 0x3F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x3F, 0x3F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x08, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0xFF, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0xFF, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0xFF, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0xFF, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x08, 0xFF, 0x3F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x08, 0xFF, 0xF8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x08, 0xFF, 0xFF, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x07, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x80, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x1F, 0x80, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xF8, 0x80, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0x80, 0x07, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xFF, 0x80, 0x08, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xFF, 0x3F, 0x80, 0x08, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xFF, 0xF8, 0x80, 0x08, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xFF, 0xFF, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xFF, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xFF, 0x3F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xFF, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x3F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xF8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xFF, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xFF, 0x3F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xFF, 0xF8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xFF, 0xFF, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x00, 0x77, 0x80, 0x0F, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x80, 0x09, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0xFC, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x80, 0x09, 0xFC, 0x0C, 0xEC, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x80, 0x09, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0x7F, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x80, 0x09, 0x7F, 0x60, 0x6F, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x80, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x80, 0x07, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0xFC, 0x80, 0x08, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0xEC, 0x0C, 0xFC, 0x80, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x80, 0x07, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x7F, 0x80, 0x08, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6F, 0x60, 0x7F, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0xEC, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x80, 0x0F, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0xEC, 0x0C, 0xEC, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6F, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x80, 0x0F, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6F, 0x60, 0x6F, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x80, 0x07, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0xFF, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x80, 0x06, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x80, 0x07, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0xFF, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0F, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0xFF, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x80, 0x08, 0xC0, 0x70, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0x03, 0x0E, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x07, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0C, 0x0E, 0x03, 0x80, 0x07, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x70, 0xC0, 0x80, 0x0F, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01, 0x80, 0x0F, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x80, 0x0F, 0x81, 0x81, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x42, 0x42, 0x81, 0x81, 0x80, 0x00, 0x1F, 0x80, 0x00, 0xF8, 0x80, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x01, 0x3F, 0x3F, 0x80, 0x01, 0xF8, 0xF8, 0x80, 0x01, 0xFF, 0xF8, 0x80, 0x0F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x80, 0x01, 0xFF, 0x3F, 0x80, 0x0F, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x80, 0x0F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x80, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x80, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x80, 0x0F, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x80, 0x0F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x80, 0x0F, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x80, 0x0F, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0x80, 0x0F, 0xBB, 0xEE, 0xBB, 0xEE, 0xBB, 0xEE, 0xBB, 0xEE, 0xBB, 0xEE, 0xBB, 0xEE, 0xBB, 0xEE, 0xBB, 0xEE, 0x80, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x08, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x80, 0x08, 0x7F, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x7F, 0x80, 0x08, 0x3E, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x3E, 0x80, 0x08, 0x7F, 0x41, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x41, 0x7F, 0x80, 0x08, 0x7F, 0x41, 0x7F, 0x41, 0x7F, 0x41, 0x7F, 0x41, 0x7F, 0x80, 0x08, 0x7F, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x7F, 0x80, 0x08, 0x7F, 0x55, 0x7F, 0x55, 0x7F, 0x55, 0x7F, 0x55, 0x7F, 0x80, 0x08, 0x7F, 0x51, 0x63, 0x45, 0x49, 0x51, 0x63, 0x45, 0x7F, 0x80, 0x08, 0x7F, 0x45, 0x63, 0x51, 0x49, 0x45, 0x63, 0x51, 0x7F, 0x80, 0x08, 0x7F, 0x55, 0x63, 0x55, 0x49, 0x55, 0x63, 0x55, 0x7F, 0x80, 0x04, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x80, 0x04, 0x3E, 0x22, 0x22, 0x22, 0x3E, 0x80, 0x04, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x80, 0x04, 0x7F, 0x41, 0x41, 0x41, 0x7F, 0x80, 0x0B, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x80, 0x0B, 0x7F, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x7F, 0x80, 0x05, 0x7E, 0x7E, 0x7E, 0x3F, 0x3F, 0x3F, 0x80, 0x05, 0x7E, 0x42, 0x42, 0x21, 0x21, 0x3F, 0x80, 0x06, 0x08, 0x1C, 0x1C, 0x3E, 0x3E, 0x7F, 0x7F, 0x80, 0x06, 0x08, 0x14, 0x14, 0x22, 0x22, 0x41, 0x7F, 0x80, 0x03, 0x08, 0x1C, 0x1C, 0x3E, 0x80, 0x03, 0x08, 0x14, 0x14, 0x3E, 0x80, 0x0A, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x80, 0x0A, 0x01, 0x03, 0x05, 0x09, 0x11, 0x21, 0x11, 0x09, 0x05, 0x03, 0x01, 0x80, 0x04, 0x02, 0x0E, 0x1E, 0x0E, 0x02, 0x80, 0x04, 0x02, 0x0E, 0x12, 0x0E, 0x02, 0x80, 0x06, 0x01, 0x07, 0x1F, 0x7F, 0x1F, 0x07, 0x01, 0x80, 0x06, 0x01, 0x07, 0x19, 0x61, 0x19, 0x07, 0x01, 0x80, 0x06, 0x7F, 0x7F, 0x3E, 0x3E, 0x1C, 0x1C, 0x08, 0x80, 0x06, 0x7F, 0x41, 0x22, 0x22, 0x14, 0x14, 0x08, 0x80, 0x03, 0x3E, 0x1C, 0x1C, 0x08, 0x80, 0x03, 0x3E, 0x14, 0x14, 0x08, 0x80, 0x0A, 0x40, 0x60, 0x70, 0x78, 0x7C, 0x7E, 0x7C, 0x78, 0x70, 0x60, 0x40, 0x80, 0x0A, 0x40, 0x60, 0x50, 0x48, 0x44, 0x42, 0x44, 0x48, 0x50, 0x60, 0x40, 0x80, 0x04, 0x10, 0x1C, 0x1E, 0x1C, 0x10, 0x80, 0x04, 0x10, 0x1C, 0x12, 0x1C, 0x10, 0x80, 0x06, 0x40, 0x70, 0x7C, 0x7F, 0x7C, 0x70, 0x40, 0x80, 0x06, 0x40, 0x70, 0x4C, 0x43, 0x4C, 0x70, 0x40, 0x80, 0x09, 0x08, 0x1C, 0x3E, 0x3E, 0x7F, 0x7F, 0x3E, 0x3E, 0x1C, 0x08, 0x80, 0x09, 0x08, 0x14, 0x22, 0x22, 0x41, 0x41, 0x22, 0x22, 0x14, 0x08, 0x80, 0x09, 0x08, 0x14, 0x22, 0x2A, 0x5D, 0x5D, 0x2A, 0x22, 0x14, 0x08, 0x80, 0x09, 0x3C, 0x42, 0x99, 0xBD, 0xBD, 0xBD, 0xBD, 0x99, 0x42, 0x3C, 0x80, 0x09, 0x08, 0x14, 0x14, 0x22, 0x41, 0x41, 0x22, 0x14, 0x14, 0x08, 0x80, 0x09, 0x3C, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3C, 0x80, 0x09, 0x28, 0x02, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x40, 0x14, 0x80, 0x09, 0x3C, 0x66, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0x66, 0x3C, 0x80, 0x09, 0x3C, 0x42, 0x99, 0xA5, 0xA5, 0xA5, 0xA5, 0x99, 0x42, 0x3C, 0x80, 0x09, 0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, 0x80, 0x09, 0x3C, 0x4E, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x4E, 0x3C, 0x80, 0x09, 0x3C, 0x72, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0x72, 0x3C, 0x80, 0x09, 0x3C, 0x42, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, 0x80, 0x09, 0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x42, 0x3C, 0x80, 0x09, 0x3C, 0x72, 0xF1, 0xF1, 0xF1, 0x81, 0x81, 0x81, 0x42, 0x3C, 0x80, 0x09, 0x3C, 0x72, 0xF1, 0xF1, 0xF1, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, 0x80, 0x09, 0x0C, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0E, 0x0C, 0x80, 0x09, 0x30, 0x70, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x70, 0x30, 0x80, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xC3, 0xBD, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0xBD, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x06, 0xFF, 0xFF, 0xC3, 0xBD, 0x7E, 0x7E, 0x7E, 0x80, 0x08, 0x7E, 0x7E, 0x7E, 0xBD, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x04, 0x0C, 0x02, 0x01, 0x01, 0x01, 0x80, 0x04, 0x30, 0x40, 0x80, 0x80, 0x80, 0x80, 0x04, 0x80, 0x80, 0x80, 0x40, 0x30, 0x80, 0x04, 0x01, 0x01, 0x01, 0x02, 0x0C, 0x80, 0x04, 0x3C, 0x42, 0x81, 0x81, 0x81, 0x80, 0x04, 0x81, 0x81, 0x81, 0x42, 0x3C, 0x80, 0x0F, 0x80, 0x80, 0xC0, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0x80, 0x0F, 0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0F, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0x1F, 0x0F, 0x0F, 0x07, 0x07, 0x03, 0x03, 0x01, 0x01, 0x80, 0x0F, 0xFF, 0xFF, 0xFE, 0xFE, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0xC0, 0x80, 0x80, 0x80, 0x05, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x80, 0x09, 0xFF, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0xFF, 0x80, 0x09, 0xFF, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xFF, 0x80, 0x09, 0xFF, 0xFF, 0xBF, 0x9F, 0x8F, 0x8F, 0x87, 0x83, 0x81, 0xFF, 0x80, 0x09, 0xFF, 0x81, 0xC1, 0xE1, 0xF1, 0xF1, 0xF9, 0xFD, 0xFF, 0xFF, 0x80, 0x09, 0xFF, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xFF, 0x80, 0x08, 0x08, 0x08, 0x14, 0x14, 0x22, 0x22, 0x49, 0x41, 0x7F, 0x80, 0x08, 0x08, 0x08, 0x1C, 0x1C, 0x2E, 0x2E, 0x4F, 0x4F, 0x7F, 0x80, 0x08, 0x08, 0x08, 0x1C, 0x1C, 0x3A, 0x3A, 0x79, 0x79, 0x7F, 0x80, 0x0A, 0x3C, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3C, 0x80, 0x08, 0x7F, 0x49, 0x49, 0x49, 0x4F, 0x41, 0x41, 0x41, 0x7F, 0x80, 0x08, 0x7F, 0x41, 0x41, 0x41, 0x4F, 0x49, 0x49, 0x49, 0x7F, 0x80, 0x08, 0x7F, 0x41, 0x41, 0x41, 0x79, 0x49, 0x49, 0x49, 0x7F, 0x80, 0x08, 0x7F, 0x49, 0x49, 0x49, 0x79, 0x41, 0x41, 0x41, 0x7F, 0x80, 0x09, 0x3C, 0x52, 0x91, 0x91, 0x91, 0x9F, 0x81, 0x81, 0x42, 0x3C, 0x80, 0x09, 0x3C, 0x42, 0x81, 0x81, 0x9F, 0x91, 0x91, 0x91, 0x52, 0x3C, 0x80, 0x09, 0x3C, 0x42, 0x81, 0x81, 0xF9, 0x89, 0x89, 0x89, 0x4A, 0x3C, 0x80, 0x09, 0x3C, 0x4A, 0x89, 0x89, 0x89, 0xF9, 0x81, 0x81, 0x42, 0x3C, 0x80, 0x08, 0x08, 0x08, 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x08, 0x08, 0x80, 0x03, 0x0C, 0x3E, 0x7F, 0xFF, 0x80, 0x08, 0x1C, 0x3E, 0x7F, 0x08, 0x08, 0x08, 0x08, 0x28, 0x10, 0x80, 0x07, 0x08, 0x08, 0x14, 0x77, 0x22, 0x2A, 0x36, 0x22, 0x80, 0x08, 0x10, 0x18, 0x0C, 0x06, 0x03, 0x06, 0x2C, 0x38, 0x3C, 0x80, 0x08, 0x7F, 0x63, 0x33, 0x1B, 0x0F, 0x1B, 0xB3, 0xE3, 0xF3, 0x80, 0x06, 0x1C, 0x22, 0x41, 0x49, 0x41, 0x22, 0x1C, 0x80, 0x07, 0x18, 0x24, 0x42, 0x42, 0x42, 0xA5, 0xA5, 0x42, 0x80, 0x07, 0x42, 0xA5, 0xA5, 0x42, 0x42, 0x42, 0x24, 0x18, 0x80, 0x06, 0x60, 0x30, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x09, 0x38, 0x6C, 0x6C, 0x38, 0x18, 0x0C, 0x0E, 0x1B, 0x1B, 0x0E, 0x80, 0x07, 0x7F, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x7F, 0x80, 0x07, 0x7F, 0x41, 0x61, 0x51, 0x5D, 0x49, 0x41, 0x7F, 0x80, 0x07, 0x7F, 0x41, 0x77, 0x5D, 0x5D, 0x77, 0x41, 0x7F, 0x80, 0x08, 0x41, 0x63, 0x36, 0x3E, 0x1C, 0x3E, 0x36, 0x63, 0x41, 0x80, 0x07, 0x3E, 0x41, 0x55, 0x41, 0x22, 0x3E, 0x22, 0x1C, 0x80, 0x04, 0x22, 0x63, 0x1C, 0x63, 0x22, 0x80, 0x07, 0x1C, 0x22, 0x77, 0x7F, 0x49, 0x5D, 0x3E, 0x1C, 0x80, 0x09, 0x18, 0x7E, 0x18, 0x18, 0xFF, 0x18, 0x78, 0x1E, 0x18, 0x18, 0x80, 0x09, 0x18, 0x7E, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x08, 0x1C, 0x08, 0x08, 0x49, 0x7F, 0x49, 0x08, 0x08, 0x1C, 0x80, 0x09, 0x3C, 0x4E, 0x07, 0x23, 0xFB, 0x73, 0x53, 0x07, 0x4E, 0x3C, 0x80, 0x08, 0x2A, 0x14, 0x2A, 0x55, 0x55, 0x55, 0x55, 0x2A, 0x1C, 0x80, 0x09, 0x3C, 0x5A, 0x99, 0x99, 0x99, 0xBD, 0xFF, 0xDB, 0x5A, 0x3C, 0x80, 0x09, 0x3C, 0x42, 0x81, 0xA1, 0x8D, 0x9F, 0xFF, 0xFB, 0x7E, 0x3C, 0x80, 0x09, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0x81, 0x99, 0xA5, 0x81, 0x7E, 0x80, 0x09, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xA5, 0x99, 0x81, 0x81, 0x7E, 0x80, 0x09, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xDB, 0xE7, 0xFF, 0xFF, 0x7E, 0x80, 0x08, 0x08, 0x08, 0x2A, 0x14, 0x63, 0x14, 0x2A, 0x08, 0x08, 0x80, 0x09, 0x1E, 0x28, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x28, 0x1E, 0x80, 0x09, 0x78, 0x14, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x14, 0x78, 0x80, 0x0B, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x80, 0x09, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x80, 0x09, 0x18, 0x18, 0x7E, 0x18, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x80, 0x09, 0x78, 0x60, 0x70, 0x58, 0x1E, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x80, 0x0C, 0xC0, 0xC0, 0xDE, 0xF3, 0xF3, 0xF3, 0xF0, 0xD8, 0xCC, 0xFF, 0xC0, 0xC0, 0xC0, 0x80, 0x09, 0x06, 0x0F, 0x06, 0x76, 0xCE, 0xC6, 0xC6, 0x66, 0x66, 0xC6, 0x80, 0x0A, 0x6B, 0x2A, 0x2A, 0x3E, 0x2A, 0x2A, 0x6B, 0x1C, 0x22, 0x22, 0x1C, 0x80, 0x0B, 0x18, 0x3C, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x3C, 0x18, 0x3C, 0x18, 0x18, 0x80, 0x0A, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x1F, 0x03, 0x03, 0x03, 0x03, 0x7F, 0x80, 0x0A, 0x42, 0xA5, 0xA5, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x80, 0x0A, 0xC3, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x80, 0x09, 0xC3, 0x7E, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7E, 0xC3, 0x80, 0x03, 0x7E, 0xDB, 0x1B, 0x0E, 0x80, 0x03, 0x70, 0xD8, 0xDB, 0x7E, 0x80, 0x0B, 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0xD8, 0xDE, 0xDB, 0xDB, 0xCE, 0xC0, 0x80, 0x80, 0x0B, 0x29, 0x3E, 0xAA, 0xEA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x60, 0xD0, 0x80, 0x06, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x24, 0xE7, 0x80, 0x0B, 0x29, 0x3E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x20, 0xC0, 0x80, 0x07, 0xF8, 0xE0, 0xF1, 0xDB, 0xCE, 0x0E, 0x1B, 0x11, 0x80, 0x0B, 0x09, 0x0A, 0x0E, 0x16, 0x12, 0x12, 0x72, 0x92, 0x90, 0x70, 0x08, 0x04, 0x80, 0x0A, 0xC3, 0x66, 0x66, 0x66, 0x66, 0xFF, 0x66, 0x66, 0x66, 0x66, 0xC3, 0x80, 0x08, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x3C, 0x80, 0x07, 0x36, 0x49, 0x41, 0x41, 0x41, 0x22, 0x14, 0x08, 0x80, 0x06, 0x08, 0x14, 0x22, 0x41, 0x22, 0x14, 0x08, 0x80, 0x08, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x18, 0x18, 0x3C, 0x80, 0x08, 0x18, 0x24, 0x42, 0x81, 0x81, 0x66, 0x18, 0x18, 0x3C, 0x80, 0x07, 0x36, 0x7F, 0x7F, 0x7F, 0x7F, 0x3E, 0x1C, 0x08, 0x80, 0x06, 0x08, 0x1C, 0x3E, 0x7F, 0x3E, 0x1C, 0x08, 0x80, 0x08, 0x18, 0x24, 0x3C, 0xE7, 0xA5, 0xE7, 0x18, 0x18, 0x3C, 0x80, 0x09, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1C, 0x1E, 0x0E, 0x80, 0x09, 0x0C, 0x3C, 0x7C, 0x4C, 0x0C, 0x0C, 0x0C, 0x0E, 0x0F, 0x07, 0x80, 0x0A, 0x0E, 0xFE, 0xF6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, 0xE7, 0xE3, 0x60, 0x80, 0x0A, 0xFE, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xE7, 0xE7, 0x63, 0x80, 0x09, 0x03, 0x03, 0x03, 0x03, 0x33, 0x7B, 0x67, 0x23, 0x1B, 0x07, 0x80, 0x0B, 0x02, 0x02, 0x22, 0x3A, 0x2E, 0x22, 0x22, 0x3A, 0x2E, 0x22, 0x20, 0x20, 0x80, 0x0B, 0x20, 0x20, 0x62, 0x3A, 0x2E, 0x23, 0x62, 0x3A, 0x2E, 0x23, 0x02, 0x02, 0x80, 0x09, 0xDC, 0x66, 0x66, 0x66, 0xFF, 0x66, 0x66, 0x66, 0x66, 0xFF, 0x80, 0x09, 0x3C, 0x76, 0x66, 0x06, 0x7F, 0x66, 0x66, 0x66, 0x66, 0xFF, 0x80, 0x09, 0x7C, 0x76, 0x66, 0x66, 0x7F, 0x66, 0x66, 0x66, 0x66, 0xFF, 0x80, 0x09, 0x76, 0xDB, 0xDB, 0x1B, 0xFF, 0xDB, 0xDB, 0xDB, 0xDB, 0xFF, 0x80, 0x09, 0xF6, 0xDB, 0xDB, 0xDB, 0xFF, 0xDB, 0xDB, 0xDB, 0xDB, 0xFF, 0x80, 0x09, 0x1C, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, 0x36, 0xB6, 0x6F, 0x80, 0x08, 0x0E, 0xF1, 0x4C, 0x82, 0x11, 0x01, 0x11, 0x02, 0x7C, 0x80, 0x08, 0x0E, 0xF1, 0x4C, 0x82, 0x01, 0x29, 0x01, 0x02, 0x7C, 0x80, 0x08, 0x0E, 0xF1, 0x4C, 0x82, 0x29, 0x01, 0x11, 0x02, 0x7C, 0x80, 0x08, 0x0E, 0xF1, 0x4C, 0x82, 0x29, 0x01, 0x29, 0x02, 0x7C, 0x80, 0x08, 0x04, 0x1C, 0x14, 0x0E, 0x10, 0x10, 0x20, 0x62, 0x9C, 0x80, 0x07, 0x80, 0x40, 0x20, 0x10, 0x12, 0x21, 0x41, 0xBE, 0x80, 0x08, 0x25, 0x90, 0x48, 0x20, 0x10, 0x12, 0x21, 0x41, 0xBE, 0x80, 0x08, 0x45, 0x30, 0xC8, 0x30, 0x08, 0x10, 0x20, 0x20, 0x1F, 0x80, 0x08, 0x45, 0x30, 0xC8, 0x30, 0x08, 0x08, 0x10, 0x20, 0xDF, 0x80, 0x08, 0x0E, 0x01, 0x0E, 0x01, 0x08, 0x16, 0x11, 0x2E, 0xC0, 0x80, 0x04, 0x08, 0x0F, 0x08, 0x28, 0x10, 0x80, 0x04, 0x08, 0xEF, 0x10, 0x10, 0x10, 0x80, 0x05, 0x08, 0x1C, 0x32, 0x4A, 0x4C, 0x3F, 0x80, 0x05, 0x08, 0x1C, 0x32, 0x4A, 0x4C, 0xBF, 0x80, 0x08, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x28, 0x06, 0x01, 0x7F, 0x80, 0x06, 0x54, 0x40, 0x4C, 0x42, 0x4C, 0x63, 0x9E, 0x80, 0x06, 0xC5, 0x30, 0x08, 0x10, 0x20, 0x20, 0x1F, 0x80, 0x06, 0xC5, 0x30, 0x08, 0x08, 0x10, 0x20, 0xDF, 0x80, 0x04, 0x08, 0x14, 0x18, 0x08, 0x04, 0x80, 0x06, 0x30, 0x48, 0xF0, 0x40, 0x3C, 0x18, 0x06, 0x80, 0x05, 0xE0, 0x11, 0xE1, 0x81, 0x7E, 0x08, 0x80, 0x08, 0x04, 0x04, 0x04, 0x04, 0x10, 0x20, 0x40, 0x42, 0x3C, 0x80, 0x08, 0x18, 0x24, 0x19, 0x06, 0x43, 0x48, 0x49, 0x39, 0x06, 0x80, 0x07, 0x40, 0x49, 0x39, 0x06, 0x70, 0x0E, 0x70, 0x0E, 0x80, 0x05, 0x18, 0x06, 0x20, 0x2A, 0x1A, 0x04, 0x80, 0x07, 0x08, 0x14, 0x08, 0x06, 0x20, 0x2A, 0x1A, 0x04, 0x80, 0x05, 0x20, 0x2A, 0x1A, 0x04, 0x30, 0x0C, 0x80, 0x05, 0x08, 0x08, 0x20, 0x2A, 0x1A, 0x04, 0x80, 0x05, 0x70, 0x0F, 0x40, 0x49, 0x39, 0x06, 0x80, 0x08, 0x18, 0x24, 0x18, 0x06, 0x40, 0x49, 0x39, 0x06, 0xFF, 0x80, 0x05, 0x40, 0x48, 0x39, 0x06, 0x70, 0x0E, 0x80, 0x08, 0x08, 0x14, 0x0A, 0x14, 0x10, 0x10, 0x10, 0x10, 0xE0, 0x80, 0x08, 0x10, 0x28, 0x14, 0x28, 0x20, 0x20, 0x20, 0x20, 0x20, 0x80, 0x08, 0x20, 0x10, 0x08, 0x2A, 0x1C, 0x2A, 0x08, 0x10, 0x20, 0x80, 0x08, 0x04, 0x08, 0x10, 0x54, 0x38, 0x54, 0x10, 0x08, 0x04, 0x80, 0x01, 0x54, 0x28, 0x80, 0x04, 0x84, 0x96, 0x95, 0x96, 0x68, 0x80, 0x01, 0x08, 0x10, 0x80, 0x03, 0x18, 0x24, 0x10, 0x08, 0x80, 0x06, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x80, 0x06, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x80, 0x06, 0x18, 0x08, 0x08, 0x04, 0x08, 0x08, 0x18, 0x80, 0x06, 0x18, 0x10, 0x10, 0x20, 0x10, 0x10, 0x18, 0x80, 0x06, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x80, 0x06, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x18, 0x80, 0x04, 0x14, 0x3E, 0x14, 0x3E, 0x14, 0x80, 0x06, 0x08, 0x14, 0x14, 0x08, 0x54, 0x24, 0x58, 0x80, 0x05, 0x08, 0x08, 0x3E, 0x1C, 0x1C, 0x22, 0x80, 0x04, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x80, 0x04, 0x10, 0x08, 0x04, 0x08, 0x10, 0x80, 0x04, 0x04, 0x08, 0x10, 0x08, 0x04, 0x80, 0x05, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x80, 0x07, 0x08, 0x1C, 0x2A, 0x0C, 0x18, 0x2A, 0x1C, 0x08, 0x80, 0x05, 0x24, 0x10, 0x10, 0x08, 0x08, 0x24, 0x80, 0x05, 0x1C, 0x22, 0x2A, 0x1A, 0x02, 0x1C, 0x80, 0x05, 0x60, 0x18, 0x06, 0x60, 0x18, 0x06, 0x80, 0x04, 0x18, 0x24, 0x28, 0x18, 0x06, 0x80, 0x04, 0x40, 0x48, 0x49, 0x39, 0x06, 0x80, 0x08, 0x80, 0x7C, 0x02, 0x10, 0x10, 0x10, 0x10, 0x10, 0xE0, 0x80, 0x08, 0x30, 0x08, 0x70, 0x08, 0x20, 0x20, 0x20, 0x20, 0xC0, 0x80, 0x0A, 0x0C, 0x02, 0x1C, 0x02, 0xE0, 0x10, 0x11, 0x61, 0x81, 0x81, 0x7E, 0x80, 0x03, 0x0C, 0x02, 0x1C, 0x02, 0x80, 0x07, 0x38, 0x04, 0x38, 0x04, 0x10, 0x20, 0x20, 0x1F, 0x80, 0x05, 0x10, 0x10, 0x10, 0x10, 0x10, 0xE0, 0x80, 0x08, 0x0E, 0xF1, 0x4C, 0x82, 0x01, 0x11, 0x01, 0x02, 0x7C, 0x80, 0x06, 0x04, 0x04, 0x04, 0x34, 0x4C, 0x45, 0xBE, 0x80, 0x06, 0x04, 0x04, 0x04, 0x34, 0x4C, 0x44, 0x3F, 0x80, 0x06, 0x04, 0x04, 0x04, 0x34, 0x4C, 0x44, 0xBF, 0x80, 0x06, 0x24, 0x04, 0x04, 0x34, 0x4C, 0x45, 0xBE, 0x80, 0x06, 0x24, 0x04, 0x04, 0x34, 0x4C, 0x44, 0x3F, 0x80, 0x06, 0x24, 0x04, 0x04, 0x34, 0x4C, 0x44, 0xBF, 0x80, 0x07, 0x60, 0x90, 0x92, 0xE1, 0x81, 0x81, 0x42, 0x3C, 0x80, 0x06, 0x4C, 0x42, 0x4C, 0x42, 0x40, 0x61, 0x9E, 0x80, 0x0A, 0x40, 0x40, 0x40, 0x40, 0x40, 0xC0, 0x42, 0x41, 0x41, 0x21, 0x1E, 0x80, 0x06, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x80, 0x06, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xEF, 0x80, 0x07, 0x10, 0x3C, 0xD2, 0x52, 0x22, 0x02, 0x02, 0x02, 0x80, 0x03, 0x30, 0x48, 0x4C, 0x33, 0x80, 0x03, 0x30, 0x48, 0x4C, 0xB3, 0x80, 0x06, 0x10, 0x80, 0x82, 0x81, 0x81, 0x42, 0x3C, 0x80, 0x07, 0x10, 0x28, 0x24, 0x14, 0xCF, 0x24, 0x18, 0x30, 0x80, 0x09, 0x16, 0x09, 0x40, 0x44, 0x48, 0x50, 0x20, 0x30, 0x48, 0x3C, 0x80, 0x08, 0x16, 0x09, 0x40, 0x4C, 0x48, 0x50, 0x50, 0x70, 0xBC, 0x80, 0x09, 0x06, 0x01, 0x4E, 0x45, 0x48, 0x50, 0x20, 0x30, 0x48, 0x3C, 0x80, 0x08, 0x0C, 0x02, 0x5C, 0x4A, 0x48, 0x50, 0x50, 0x70, 0xBC, 0x80, 0x09, 0x8F, 0xAC, 0xAA, 0x51, 0x07, 0x60, 0xA9, 0x6B, 0xAD, 0xE9, 0x80, 0x04, 0x77, 0x51, 0x77, 0x14, 0x17, 0x80, 0x0B, 0x1C, 0x3E, 0x3E, 0x63, 0x49, 0x4F, 0x67, 0x7F, 0x67, 0x3E, 0x3E, 0x1C, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCB, 0x0C, 0x00, 0x9E, 0x00, 0x00, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x75, 0x06, 0x00, 0x00, 0x0A, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD7, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xDD, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE8, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xF8, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x02, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0E, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x14, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x20, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2C, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7D, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x09, 0xE6, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0A, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x33, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3D, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x49, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x55, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x61, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6D, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x79, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x85, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9D, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA9, 0x0D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x83, 0x00, 0x00, 0x00, 0x09, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x83, 0x00, 0x00, 0x00, 0x09, 0xD8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xB5, 0x0D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB2, 0x00, 0x00, 0x00, 0x08, 0xB2, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xC0, 0x0D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCB, 0x0D, 0x00, 0x00, 0x0A, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xD4, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8B, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x97, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEC, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x84, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA3, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDF, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7E, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF2, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8A, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFE, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBB, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC7, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD3, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x90, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF8, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEB, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9C, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA8, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x49, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB4, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x04, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x96, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC0, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCC, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD8, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF9, 0x0D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x05, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x10, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xA2, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0D, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE4, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x10, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC0, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDF, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1C, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x9F, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE9, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x55, 0x02, 0x00, 0x00, 0x05, 0xEB, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF5, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF7, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x03, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x71, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x01, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x28, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7A, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x83, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0D, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x19, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC9, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x0A, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x34, 0x0E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x22, 0x04, 0x00, 0x00, 0x07, 0x1C, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x40, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xA8, 0x06, 0x00, 0x9F, 0x00, 0x00, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0x4C, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x55, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x62, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x6F, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x78, 0x0E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x22, 0x04, 0x00, 0x00, 0x07, 0x1C, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x84, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x92, 0x0E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x9E, 0x0E, 0x00, 0x00, 0x06, 0xB2, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA4, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xAB, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xD2, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB2, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xB1, 0x06, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x7D, 0x03, 0x00, 0x00, 0x0A, 0xB2, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xB7, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xBF, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC7, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBB, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xC7, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD3, 0x06, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xB1, 0x06, 0x00, 0x00, 0x06, 0x8A, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xCC, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD3, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xE2, 0x0E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xF1, 0x0E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0x03, 0x3A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x3A, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDB, 0x06, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x03, 0x3A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0x3A, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x09, 0x0F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE9, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF5, 0x06, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x13, 0x02, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x13, 0x02, 0x00, 0x00, 0x03, 0x5B, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x5B, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x17, 0x0F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x03, 0x5B, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x23, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0x03, 0x66, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x66, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x12, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x03, 0x66, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0x66, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x25, 0x0F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2C, 0x0F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0x03, 0xAB, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0xAB, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x38, 0x0F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0xAB, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x17, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x46, 0x0F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x52, 0x0F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD4, 0x00, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x15, 0x03, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD5, 0x01, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x33, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2F, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD4, 0x00, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x13, 0x02, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE6, 0x00, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5E, 0x0F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x00, 0x05, 0x71, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD4, 0x00, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x83, 0x00, 0x00, 0x00, 0x07, 0xB2, 0x00, 0x00, 0x00, 0x09, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x20, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD4, 0x00, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x15, 0x03, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3B, 0x05, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6A, 0x0F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0x3A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x03, 0x3A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x79, 0x0F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x88, 0x0F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x29, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0xC0, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x94, 0x0F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0xC0, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x03, 0x29, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x00, 0x00, 0x00, 0x05, 0xC0, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xA2, 0x0F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x05, 0xC0, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB0, 0x0F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBE, 0x0F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x23, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x34, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x00, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xCC, 0x0F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xDA, 0x0F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE6, 0x0F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF4, 0x0F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0x9F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x03, 0x3C, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x05, 0x9F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x03, 0x3C, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x00, 0x00, 0x00, 0x05, 0x9F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7E, 0x06, 0x00, 0x00, 0x0D, 0xD8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x3F, 0x05, 0x00, 0x00, 0x05, 0x9F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x03, 0x44, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x14, 0x10, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x40, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x03, 0x5B, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xB2, 0x00, 0x00, 0x00, 0x03, 0x5B, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xB2, 0x00, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x4C, 0x07, 0x00, 0x00, 0x03, 0x5B, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x4C, 0x07, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x20, 0x10, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0x2E, 0x10, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x03, 0x5B, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3A, 0x10, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE6, 0x00, 0x00, 0x00, 0x05, 0x46, 0x10, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x52, 0x10, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x60, 0x10, 0x00, 0x00, 0x05, 0xEB, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFE, 0x01, 0x00, 0x00, 0x0D, 0xD8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF5, 0x03, 0x00, 0x00, 0x0D, 0xD8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x47, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x15, 0x03, 0x00, 0x00, 0x03, 0x50, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x5B, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBB, 0x02, 0x00, 0x00, 0x0D, 0xD8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF7, 0x02, 0x00, 0x00, 0x0D, 0xD8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x65, 0x10, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x73, 0x10, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x81, 0x10, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x10, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x10, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA5, 0x10, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x71, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD3, 0x02, 0x00, 0x00, 0x0D, 0xD8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x71, 0x01, 0x00, 0x00, 0x0D, 0xD8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB1, 0x10, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x05, 0x71, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xBF, 0x10, 0x00, 0x00, 0x05, 0x71, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x10, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xD3, 0x10, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0x66, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x03, 0x66, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDA, 0x01, 0x00, 0x00, 0x03, 0x66, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDA, 0x01, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDF, 0x10, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xEB, 0x10, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x19, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x7A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9C, 0x03, 0x00, 0x00, 0x0D, 0xD8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7A, 0x01, 0x00, 0x00, 0x0D, 0xD8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF4, 0x10, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x05, 0x7A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x4F, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x83, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0x83, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x10, 0x11, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x1E, 0x11, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x2A, 0x11, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x05, 0x83, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x38, 0x11, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x47, 0x11, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x56, 0x11, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x64, 0x11, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x72, 0x11, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7E, 0x11, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x03, 0xAB, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0xAB, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x66, 0x07, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x03, 0xAB, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8A, 0x11, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8E, 0x11, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD5, 0x01, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDA, 0x01, 0x00, 0x00, 0x03, 0xAB, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDA, 0x01, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x9C, 0x11, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xAA, 0x11, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB6, 0x11, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0xC9, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x11, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x03, 0x17, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x69, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x0A, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x03, 0x69, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0x0A, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD2, 0x11, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x05, 0x0A, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE0, 0x11, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEC, 0x11, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF8, 0x11, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x04, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x10, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1C, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x28, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x74, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x34, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x41, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x23, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x4B, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x57, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x63, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x6F, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7B, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x80, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8C, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x87, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x96, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xA5, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB2, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC0, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCC, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD8, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE4, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF0, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFC, 0x12, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x08, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x14, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x20, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x5A, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x50, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x98, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA6, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2F, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3E, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x4A, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x56, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x65, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x72, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7E, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB2, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x87, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x96, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA5, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB1, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBD, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBE, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCC, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD8, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCC, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD8, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xE4, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF2, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xFE, 0x13, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x07, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x15, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x23, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2F, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3B, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x47, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x53, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5C, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x68, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE4, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x66, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x74, 0x14, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x75, 0x06, 0x00, 0x00, 0x0A, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8E, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9A, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA6, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB2, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC1, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD0, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDC, 0x14, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x22, 0x02, 0x00, 0x00, 0x05, 0xEB, 0x14, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF7, 0x14, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x13, 0x15, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x21, 0x15, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x8C, 0x01, 0x00, 0x00, 0x04, 0x59, 0x02, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x66, 0x07, 0x00, 0x00, 0x03, 0x5C, 0x04, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x2F, 0x15, 0x00, 0x00, 0x04, 0x59, 0x02, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x15, 0x03, 0x00, 0x00, 0x03, 0x5C, 0x04, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x34, 0x15, 0x00, 0x00, 0x04, 0x59, 0x02, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x39, 0x15, 0x00, 0x00, 0x03, 0x5C, 0x04, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x3D, 0x15, 0x00, 0x00, 0x04, 0x59, 0x02, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0x03, 0x5C, 0x04, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x5F, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x42, 0x15, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0x8C, 0x01, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x4E, 0x15, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0x72, 0x05, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0xF0, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0x33, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5C, 0x15, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x68, 0x15, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x74, 0x15, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x05, 0x9F, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x82, 0x15, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x90, 0x15, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9E, 0x15, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xFB, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0xAD, 0x15, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0xFB, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBB, 0x15, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x05, 0x75, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xCB, 0x15, 0x00, 0x00, 0x05, 0xEB, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD0, 0x15, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDC, 0x15, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x07, 0x08, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x3C, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x15, 0x03, 0x00, 0x00, 0x05, 0x9F, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE8, 0x15, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF4, 0x15, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x13, 0x02, 0x00, 0x00, 0x05, 0x71, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x03, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x11, 0x16, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0xF0, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x33, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x1F, 0x16, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x20, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x03, 0x3A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x14, 0x01, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB6, 0x01, 0x00, 0x00, 0x03, 0x3A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB6, 0x01, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x14, 0x01, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB6, 0x01, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB6, 0x01, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x03, 0x5B, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x14, 0x01, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x13, 0x08, 0x00, 0x00, 0x03, 0x5B, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x13, 0x08, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x03, 0x66, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x14, 0x01, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB6, 0x01, 0x00, 0x00, 0x03, 0x66, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB6, 0x01, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x03, 0x19, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x14, 0x01, 0x00, 0x00, 0x05, 0x7A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB6, 0x01, 0x00, 0x00, 0x03, 0x19, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB6, 0x01, 0x00, 0x00, 0x05, 0x7A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x03, 0xAB, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x14, 0x01, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB6, 0x01, 0x00, 0x00, 0x03, 0xAB, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2A, 0x16, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA8, 0x03, 0x00, 0x00, 0x0D, 0xD8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x83, 0x01, 0x00, 0x00, 0x0D, 0xD8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x49, 0x02, 0x00, 0x00, 0x0D, 0xD8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0D, 0x04, 0x00, 0x00, 0x0D, 0xD8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2E, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3C, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x47, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x55, 0x16, 0x00, 0x81, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x63, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6F, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7B, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x89, 0x16, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x03, 0x3A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x00, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x94, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x17, 0x08, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x8C, 0x01, 0x00, 0x00, 0x04, 0x68, 0x04, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0x8C, 0x01, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x23, 0x08, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x03, 0x66, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x00, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x72, 0x05, 0x00, 0x00, 0x04, 0x68, 0x04, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0x72, 0x05, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD2, 0x01, 0x00, 0x00, 0x03, 0x17, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x9B, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA3, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xAC, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB5, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBE, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xCA, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xD3, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDD, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEC, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF8, 0x16, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x5F, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x01, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x81, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x8A, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x0A, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x13, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x1C, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x28, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x9F, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x36, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2F, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3F, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x48, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x54, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x60, 0x17, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0x6F, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x24, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x78, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x81, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA8, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB7, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC0, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xCC, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xD8, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE4, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF0, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x72, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF9, 0x17, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x93, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3B, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x02, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0B, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x17, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x23, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2F, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3B, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x44, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x4D, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x56, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x5F, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6B, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7A, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x89, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x93, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA0, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAC, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xBB, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC4, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2D, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xCD, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xD6, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDF, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xEB, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF4, 0x18, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x75, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x0A, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x16, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x22, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2E, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3A, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x46, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x4A, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x52, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x5B, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x53, 0x08, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x65, 0x19, 0x00, 0x00, 0x05, 0x69, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x75, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x81, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x98, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA4, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x07, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB0, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBF, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCC, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD8, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE7, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF3, 0x19, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x02, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0E, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1A, 0x1A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5C, 0x08, 0x00, 0x00, 0x08, 0x5C, 0x08, 0x00, 0x81, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x26, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x2E, 0x1A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x03, 0x36, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x3D, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x43, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x49, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x50, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x58, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x5E, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x62, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x65, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x3F, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xE4, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x67, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x6A, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6F, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x76, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x84, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8B, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x93, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x26, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD4, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x26, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0D, 0x9B, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0D, 0x9F, 0x1A, 0x00, 0x87, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD5, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xA3, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDA, 0x01, 0x00, 0x8F, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xA8, 0x1A, 0x00, 0x90, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD4, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAE, 0x1A, 0x00, 0x84, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x6C, 0x08, 0x00, 0x87, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x3F, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xE4, 0x03, 0x00, 0x8D, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x9B, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB2, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB6, 0x1A, 0x00, 0xB1, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xBA, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0A, 0xBF, 0x1A, 0x00, 0x83, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xC4, 0x1A, 0x00, 0x82, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x83, 0x00, 0x00, 0x00, 0x09, 0xD8, 0x00, 0x00, 0x84, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC9, 0x1A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x8C, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xCD, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDB, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE9, 0x1A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF7, 0x1A, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x05, 0x1B, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x13, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x21, 0x1B, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x8C, 0x01, 0x00, 0x00, 0x05, 0x24, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8B, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x97, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x71, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA3, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD8, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x50, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF2, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFE, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2F, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC7, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD3, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3B, 0x1B, 0x00, 0x00, 0x09, 0x43, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x90, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x89, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF8, 0x04, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB2, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x49, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCC, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC0, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x48, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA1, 0x08, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x03, 0x5B, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x03, 0x17, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x8F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x81, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x5A, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x24, 0x03, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x8C, 0x01, 0x00, 0x00, 0x05, 0x2D, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x8F, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x54, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2F, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x63, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x81, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6F, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x5A, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7E, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x24, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x47, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8A, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC7, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x96, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9F, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xAE, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB7, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC3, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xCE, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xD7, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2D, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE0, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xEC, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF8, 0x1B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x93, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE6, 0x00, 0x00, 0x00, 0x05, 0x24, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0x2D, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x2D, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x93, 0x05, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x04, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x10, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1C, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x28, 0x1C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0x36, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3B, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x41, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x4A, 0x1C, 0x00, 0x81, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x55, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x63, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6F, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7B, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x87, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x94, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA0, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xAF, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBC, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xCA, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD5, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE1, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xED, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xFC, 0x1C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x06, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x12, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1E, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2A, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x33, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3F, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x48, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x54, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x60, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x69, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC0, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x55, 0x02, 0x00, 0x00, 0x05, 0xEB, 0x02, 0x00, 0x8B, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x13, 0x02, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x75, 0x1D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x83, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8E, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA8, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF2, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x03, 0x5B, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8A, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9A, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA6, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB2, 0x1D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0xAD, 0x08, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x13, 0x02, 0x00, 0x00, 0x03, 0x9C, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x03, 0x7B, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBE, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8B, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCD, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x97, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x71, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD9, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA3, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE7, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF3, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFF, 0x1D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFE, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x19, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC7, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x90, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x89, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF8, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEC, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x49, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x25, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC0, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x31, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3F, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x4B, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x57, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x65, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x71, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x89, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA1, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAD, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x4A, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB8, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB9, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA7, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x8A, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x36, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x05, 0x36, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x47, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC4, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xCD, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x53, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xD6, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x01, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC0, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xDF, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xE8, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF5, 0x1E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC1, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x09, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x14, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xCA, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x1D, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xD3, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x26, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2F, 0x1F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD4, 0x00, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x38, 0x1F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x47, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x83, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE6, 0x00, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x55, 0x02, 0x00, 0x00, 0x05, 0xEB, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x50, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x59, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x40, 0x07, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x47, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD4, 0x00, 0x00, 0x00, 0x05, 0x36, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x62, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6E, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB0, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7A, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x86, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x92, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x9E, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA7, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB3, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBC, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC8, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD1, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xDD, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE6, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF2, 0x1F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xFB, 0x1F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00, 0x05, 0x0B, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x16, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x22, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x50, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x72, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x31, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xDC, 0x08, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x03, 0x3D, 0x20, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x14, 0x01, 0x00, 0x00, 0x05, 0xDC, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x48, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x57, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x63, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x71, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7C, 0x20, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xE5, 0x08, 0x00, 0x00, 0x05, 0xB0, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xEA, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x20, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEA, 0x08, 0x00, 0x00, 0x05, 0xB0, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA4, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xE5, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xBB, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xC0, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xC5, 0x20, 0x00, 0x80, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xB9, 0x05, 0x00, 0x00, 0x06, 0xCA, 0x20, 0x00, 0x00, 0x08, 0xEE, 0x08, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCD, 0x20, 0x00, 0x00, 0x06, 0xD2, 0x20, 0x00, 0x00, 0x09, 0xD6, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDB, 0x20, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x05, 0xEB, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xF6, 0x20, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x03, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0D, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x19, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x25, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x33, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3E, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x4A, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x53, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x62, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6E, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7C, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x87, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x96, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA2, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB0, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBB, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC7, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD0, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDC, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE8, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF4, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF2, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFD, 0x21, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x09, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x12, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x21, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2D, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x39, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF5, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2F, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x42, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x50, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCC, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x5B, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x67, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x73, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7F, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x8D, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x98, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA6, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB1, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xBF, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCA, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xD6, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDF, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xEB, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF4, 0x22, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x09, 0x23, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x18, 0x23, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF2, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x24, 0x23, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x05, 0xA7, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x32, 0x23, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x41, 0x23, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x4D, 0x23, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x5B, 0x23, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x66, 0x23, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x75, 0x23, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF2, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x81, 0x23, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x8F, 0x23, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9A, 0x23, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA8, 0x23, 0x00, 0x80, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x03, 0x3A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0x3A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE9, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x33, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x80, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x5F, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0xB3, 0x23, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0x5F, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0xBE, 0x23, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0xA7, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0xC9, 0x23, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0x8A, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD4, 0x23, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x75, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0x9C, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0x36, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0x9C, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0x36, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0x66, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x50, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x72, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x23, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0x72, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0xEB, 0x23, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0xD3, 0x08, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0x7B, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0x7B, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDA, 0x01, 0x00, 0x00, 0x03, 0x7B, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDA, 0x01, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0xF6, 0x23, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0xC1, 0x08, 0x00, 0x81, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0x01, 0x24, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0xCA, 0x08, 0x00, 0x85, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0C, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDF, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x18, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x24, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x30, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3C, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x45, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x53, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5E, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x6A, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x73, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7F, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x88, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x94, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9D, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA9, 0x24, 0x00, 0x9F, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xB2, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBB, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC7, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD3, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDF, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEB, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF7, 0x24, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x04, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x11, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1D, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x29, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x35, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x41, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x4E, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5A, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x66, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x72, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7F, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8B, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x97, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA3, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBB, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC7, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD3, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDF, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEB, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF7, 0x25, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x04, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x10, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1C, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x28, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x34, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x40, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x4C, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x58, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x64, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x70, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7C, 0x26, 0x00, 0x81, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x88, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8E, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x62, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x94, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x99, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x9E, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xA3, 0x26, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA8, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB1, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xBD, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC9, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD5, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE1, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xED, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xFB, 0x26, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x07, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x13, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1F, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2E, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3A, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x49, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x55, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x64, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x70, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7C, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x88, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x94, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA0, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAC, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB8, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC4, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xCD, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xD9, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE5, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF1, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xFA, 0x27, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x03, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x12, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x1B, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x27, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x33, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3C, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x4B, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x57, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x60, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6F, 0x28, 0x00, 0x80, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x83, 0x00, 0x00, 0x00, 0x0A, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7B, 0x28, 0x00, 0x85, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x80, 0x28, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0xBD, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x86, 0x28, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8D, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x92, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x97, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x9C, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xA1, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xA6, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xAB, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB0, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB5, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBA, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBF, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC5, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xCB, 0x28, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x0B, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x10, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xD1, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xD6, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xDB, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE1, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE6, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xEC, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xF2, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF7, 0x28, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD5, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x01, 0x01, 0x00, 0x00, 0x0E, 0x01, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xFC, 0x28, 0x00, 0x00, 0x0E, 0xFF, 0x28, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x02, 0x29, 0x00, 0x00, 0x0E, 0x05, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x08, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x01, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xBD, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xBD, 0x05, 0x00, 0x00, 0x0E, 0x01, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0D, 0xB2, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0D, 0x0D, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xC0, 0x05, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x12, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0D, 0x26, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x17, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8A, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x15, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x55, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x3F, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x83, 0x00, 0x00, 0x00, 0x0A, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x83, 0x00, 0x00, 0x8A, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x1B, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x25, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x2F, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x39, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x43, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x4D, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x57, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x61, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x6B, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x75, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x7C, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x89, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x93, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x9F, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xA9, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xB3, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xC0, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xCA, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xD4, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xDE, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xEB, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xF5, 0x29, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x02, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x0C, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x19, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x23, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x2D, 0x2A, 0x00, 0x84, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x37, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x41, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x4B, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDA, 0x01, 0x00, 0x96, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x52, 0x2A, 0x00, 0x8D, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x58, 0x2A, 0x00, 0x00, 0x08, 0x83, 0x00, 0x00, 0x82, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5D, 0x2A, 0x00, 0x00, 0x09, 0x7D, 0x00, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xC4, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x1F, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x2A, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x35, 0x09, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xCB, 0x05, 0x00, 0x00, 0x0A, 0xD3, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x65, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xCB, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x0B, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x63, 0x02, 0x00, 0x00, 0x04, 0x43, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x42, 0x09, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x49, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x66, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x86, 0x04, 0x00, 0x00, 0x04, 0x66, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x18, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x00, 0x00, 0x00, 0x04, 0x18, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x1F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x05, 0x1F, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x71, 0x02, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0x71, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x2B, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x00, 0x00, 0x00, 0x04, 0x2B, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x54, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5D, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x4A, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x56, 0x03, 0x00, 0x00, 0x04, 0x4A, 0x03, 0x00, 0x84, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0xB5, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x00, 0x00, 0x00, 0x04, 0x98, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x00, 0x00, 0x04, 0x89, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x94, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD9, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x66, 0x09, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x05, 0xDE, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x72, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x27, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE6, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE6, 0x01, 0x00, 0x00, 0x0E, 0xE5, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x9D, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7A, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0A, 0x9D, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xA3, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xA3, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x88, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8E, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x72, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x93, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x93, 0x09, 0x00, 0x89, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x77, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA4, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7C, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x87, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x92, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBA, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC5, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD0, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9D, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0xA9, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xB1, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xDB, 0x09, 0x00, 0x81, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x59, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE8, 0x05, 0x00, 0x00, 0x04, 0xE5, 0x09, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xEC, 0x09, 0x00, 0x00, 0x04, 0xE5, 0x09, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xED, 0x05, 0x00, 0x00, 0x0A, 0xEC, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xB8, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBE, 0x2A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF1, 0x09, 0x00, 0x00, 0x05, 0x27, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF7, 0x09, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF1, 0x09, 0x00, 0x00, 0x05, 0xE6, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x7D, 0x00, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x0A, 0x7D, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xC9, 0x2A, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x87, 0x00, 0x00, 0x00, 0x03, 0x7D, 0x00, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x0B, 0x87, 0x00, 0x00, 0x00, 0x0D, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x87, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x0B, 0x87, 0x00, 0x00, 0x00, 0x0D, 0x87, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD3, 0x2A, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x04, 0x66, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x05, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x10, 0x0A, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x04, 0x66, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xF5, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x1B, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xE2, 0x2A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x18, 0x01, 0x00, 0x00, 0x0B, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0B, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x87, 0x00, 0x00, 0x00, 0x04, 0x18, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x18, 0x01, 0x00, 0x00, 0x0B, 0x87, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x04, 0x18, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x04, 0x18, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x04, 0x18, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x05, 0x1F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x79, 0x02, 0x00, 0x00, 0x05, 0x1F, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xEC, 0x2A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF5, 0x2A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x1F, 0x01, 0x00, 0x00, 0x0C, 0x79, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xFD, 0x2A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x05, 0x1F, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x05, 0x1F, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x05, 0x1F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xB8, 0x00, 0x00, 0x00, 0x05, 0x05, 0x2B, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x26, 0x0A, 0x00, 0x00, 0x0C, 0x0B, 0x06, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xB8, 0x00, 0x00, 0x00, 0x03, 0xD1, 0x00, 0x00, 0x00, 0x05, 0x26, 0x0A, 0x00, 0x00, 0x0C, 0x0B, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x0D, 0x2B, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x00, 0x00, 0x04, 0x2B, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x02, 0x16, 0x2B, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x86, 0x04, 0x00, 0x00, 0x02, 0x2E, 0x0A, 0x00, 0x00, 0x04, 0x4A, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x98, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x98, 0x01, 0x00, 0x00, 0x0A, 0x0B, 0x06, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x00, 0x00, 0x00, 0x04, 0x98, 0x01, 0x00, 0x00, 0x0A, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x00, 0x00, 0x04, 0x98, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x98, 0x01, 0x00, 0x00, 0x0A, 0xD1, 0x00, 0x00, 0x00, 0x0C, 0xB8, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x00, 0x00, 0x04, 0x98, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x00, 0x00, 0x00, 0x04, 0x89, 0x04, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x00, 0x00, 0x04, 0x89, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x31, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x1F, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x28, 0x2B, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x02, 0x94, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0x02, 0x3B, 0x0A, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x94, 0x04, 0x00, 0x00, 0x0A, 0x87, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x5F, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x32, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x44, 0x0A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x5F, 0x03, 0x00, 0x00, 0x0A, 0x87, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x5F, 0x03, 0x00, 0x00, 0x0A, 0x7D, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x3D, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x48, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x55, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x62, 0x2B, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD9, 0x05, 0x00, 0x00, 0x0C, 0x87, 0x00, 0x00, 0x00, 0x0E, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x05, 0xDE, 0x01, 0x00, 0x00, 0x0D, 0xB8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xDE, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x05, 0xDE, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x05, 0x6F, 0x2B, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x05, 0xDE, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x7A, 0x2B, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x00, 0x00, 0x00, 0x04, 0xF5, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x4F, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xA7, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x2B, 0x00, 0x00, 0x07, 0xA7, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x07, 0xA7, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x89, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x5A, 0x0A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x79, 0x02, 0x00, 0x00, 0x05, 0x27, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x63, 0x0A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0E, 0x06, 0x00, 0x00, 0x05, 0x27, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x14, 0x06, 0x00, 0x00, 0x05, 0x27, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x05, 0x27, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x05, 0x27, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE6, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x92, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x9C, 0x2B, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x05, 0x27, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x18, 0x06, 0x00, 0x00, 0x0D, 0x7D, 0x00, 0x00, 0x00, 0x0F, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x18, 0x06, 0x00, 0x00, 0x0D, 0x87, 0x00, 0x00, 0x00, 0x0F, 0x7D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x71, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA7, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xD2, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x43, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB2, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBB, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xCA, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD1, 0x2B, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x78, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD9, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE9, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF7, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xFC, 0x2B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7E, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x78, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x02, 0x2C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x06, 0x2C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x85, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x85, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0E, 0x2C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x14, 0x2C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0B, 0x8B, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8B, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x21, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0B, 0x7E, 0x0A, 0x00, 0x81, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x24, 0x2C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA4, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2A, 0x2C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x35, 0x2C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x40, 0x2C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBA, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC5, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD0, 0x09, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0x4B, 0x2C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x00, 0x00, 0x00, 0x04, 0x53, 0x2C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x56, 0x03, 0x00, 0x00, 0x04, 0x5C, 0x2C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xC4, 0x05, 0x00, 0x00, 0x0A, 0x68, 0x2C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x6E, 0x2C, 0x00, 0xC9, 0xD3, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7A, 0x2C, 0x00, 0x82, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x86, 0x2C, 0x00, 0x81, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x8F, 0x2C, 0x00, 0x81, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x9B, 0x2C, 0x00, 0x87, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA4, 0x2C, 0x00, 0xCD, 0x18, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8B, 0x02, 0x00, 0x00, 0x0D, 0xD5, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x0D, 0xD5, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x03, 0xB0, 0x2C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xBB, 0x2C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x97, 0x02, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x10, 0x05, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x97, 0x02, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x10, 0x05, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0xC8, 0x2C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x2F, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x03, 0xD6, 0x2C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE1, 0x2C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x84, 0x03, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDF, 0x02, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x84, 0x03, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDF, 0x02, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEF, 0x2C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFE, 0x2C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0D, 0x2D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1C, 0x2D, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0x27, 0x06, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0x27, 0x06, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2B, 0x2D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3A, 0x2D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA3, 0x02, 0x00, 0x00, 0x0D, 0x99, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x0D, 0x99, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x03, 0x46, 0x2D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x05, 0x17, 0x08, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x03, 0x54, 0x2D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x03, 0x5F, 0x2D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0x3C, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0x9F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x03, 0x44, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x6A, 0x2D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x02, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE9, 0x03, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0x44, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0x78, 0x2D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x2D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x92, 0x2D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x02, 0x00, 0x00, 0x0D, 0xC4, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE9, 0x03, 0x00, 0x00, 0x0D, 0xC4, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF2, 0x01, 0x00, 0x00, 0x0D, 0x99, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x0D, 0x99, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xA1, 0x2D, 0x00, 0x00, 0x04, 0xA6, 0x2D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB0, 0x2D, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x03, 0xAD, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xB6, 0x2D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFE, 0x01, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF5, 0x03, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFE, 0x01, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF5, 0x03, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBB, 0x02, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF7, 0x02, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0x50, 0x07, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0x5B, 0x07, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBB, 0x02, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF7, 0x02, 0x00, 0x00, 0x0D, 0xB2, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC3, 0x2D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD2, 0x2D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x92, 0x0A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x03, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x03, 0x92, 0x0A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x00, 0x00, 0x00, 0x05, 0x03, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC7, 0x02, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x03, 0x03, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0x71, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD3, 0x02, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x71, 0x01, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD3, 0x02, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x71, 0x01, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE1, 0x2D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF0, 0x2D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xFC, 0x2D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x9D, 0x0A, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x02, 0x23, 0x08, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0A, 0x2E, 0x00, 0x00, 0x04, 0x68, 0x04, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0F, 0x2E, 0x00, 0x00, 0x04, 0x68, 0x04, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0xA3, 0x0A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0x01, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x03, 0xA3, 0x0A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0x01, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x03, 0x19, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0x7A, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9C, 0x03, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7A, 0x01, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x03, 0x19, 0x03, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x00, 0x00, 0x00, 0x05, 0x7A, 0x01, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9C, 0x03, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7A, 0x01, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x03, 0x4F, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x00, 0x00, 0x00, 0x05, 0x83, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA8, 0x03, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x83, 0x01, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x14, 0x2E, 0x00, 0x00, 0x04, 0x19, 0x2E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x23, 0x2E, 0x00, 0x00, 0x05, 0x83, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x29, 0x2E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x37, 0x2E, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x03, 0x4F, 0x05, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x00, 0x00, 0x00, 0x05, 0x83, 0x01, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x03, 0x45, 0x2E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x50, 0x2E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x49, 0x02, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0D, 0x04, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x49, 0x02, 0x00, 0x00, 0x0D, 0xB2, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0D, 0x04, 0x00, 0x00, 0x0D, 0xB2, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5D, 0x2E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6C, 0x2E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB4, 0x03, 0x00, 0x00, 0x0D, 0x95, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x0D, 0x95, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB4, 0x03, 0x00, 0x00, 0x0D, 0x99, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x0D, 0x99, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7B, 0x2E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x8A, 0x2E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x96, 0x2E, 0x00, 0x00, 0x05, 0x9C, 0x2E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x9D, 0x0A, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x02, 0x8A, 0x00, 0x00, 0x00, 0x04, 0x59, 0x02, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x3B, 0x05, 0x00, 0x00, 0x03, 0xEF, 0x01, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x03, 0xA5, 0x2E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x00, 0x05, 0x19, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x04, 0x05, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x19, 0x04, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0x03, 0xAB, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD4, 0x00, 0x00, 0x00, 0x05, 0xC9, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x03, 0xAB, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x05, 0xC9, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0xAB, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0xC9, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x03, 0xAB, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x00, 0x00, 0x00, 0x05, 0xC9, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x96, 0x06, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC9, 0x01, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x03, 0xAE, 0x0A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x00, 0x00, 0x00, 0x05, 0x0C, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0xAE, 0x0A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0x0C, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x03, 0x17, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x00, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB0, 0x2E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0x0A, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD8, 0x03, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x0A, 0x02, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD8, 0x03, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x0A, 0x02, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE9, 0x03, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x03, 0xBE, 0x2E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD5, 0x01, 0x00, 0x00, 0x05, 0xC9, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD5, 0x01, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x67, 0x08, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x03, 0xC9, 0x2E, 0x00, 0x83, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8B, 0x02, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD4, 0x2E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x6A, 0x03, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE2, 0x2E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF0, 0x2E, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF6, 0x2E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x04, 0x2F, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0A, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB6, 0x04, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x18, 0x2F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x26, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDB, 0x06, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x34, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x42, 0x2F, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x48, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x56, 0x2F, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x5C, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x6A, 0x2F, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x70, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7E, 0x2F, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x03, 0x3A, 0x01, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x05, 0x9D, 0x00, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA3, 0x02, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x84, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x6A, 0x03, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x92, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB9, 0x0A, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xA0, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBF, 0x0A, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB6, 0x04, 0x00, 0x00, 0x05, 0x27, 0x06, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB6, 0x04, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xAE, 0x2F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBC, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0xBB, 0x00, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xCA, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x6A, 0x03, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF2, 0x01, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x90, 0x03, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD8, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x6A, 0x03, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE6, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB9, 0x0A, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF4, 0x2F, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBF, 0x0A, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB6, 0x04, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x10, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x1E, 0x30, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x12, 0x07, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x05, 0xA6, 0x00, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x2C, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3A, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x46, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x54, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x6E, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7B, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x89, 0x30, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x98, 0x07, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA6, 0x07, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB4, 0x03, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x96, 0x30, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x6C, 0x08, 0x00, 0x00, 0x05, 0xC8, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xA4, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB2, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBE, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCC, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD8, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xE6, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF3, 0x30, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x01, 0x31, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBE, 0x07, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCC, 0x07, 0x00, 0x00, 0x0D, 0x8D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x13, 0x02, 0x00, 0x00, 0x03, 0x17, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD4, 0x00, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCC, 0x03, 0x00, 0x00, 0x0D, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x0E, 0x31, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x1A, 0x31, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x6A, 0x03, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x28, 0x31, 0x00, 0x00, 0x03, 0x17, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x85, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD8, 0x00, 0x00, 0x00, 0x05, 0x8F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xE4, 0x03, 0x00, 0x00, 0x05, 0x8F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x2C, 0x31, 0x00, 0x00, 0x05, 0x8F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x31, 0x31, 0x00, 0x00, 0x05, 0x8F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x36, 0x31, 0x00, 0x00, 0x05, 0x8F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x3B, 0x31, 0x00, 0x00, 0x05, 0x8F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x40, 0x31, 0x00, 0x00, 0x05, 0x8F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x46, 0x31, 0x00, 0x00, 0x05, 0x8F, 0x01, 0x00, 0xC0, 0xF7, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x4C, 0x31, 0x00, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x53, 0x31, 0x00, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x5A, 0x31, 0x00, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x61, 0x31, 0x00, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x68, 0x31, 0x00, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x6F, 0x31, 0x00, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x76, 0x31, 0x00, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x7D, 0x31, 0x00, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x84, 0x31, 0x00, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x8B, 0x31, 0x00, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x92, 0x31, 0x00, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x30, 0x06, 0x00, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x30, 0x06, 0x00, 0x00, 0x08, 0x99, 0x31, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x30, 0x06, 0x00, 0x00, 0x08, 0xA0, 0x31, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0xA7, 0x31, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0xB4, 0x31, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x8A, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xC1, 0x31, 0x00, 0x00, 0x07, 0xD2, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xB2, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xB2, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x66, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x80, 0x00, 0x00, 0x00, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xC8, 0x31, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xE6, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0A, 0xE6, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xCE, 0x31, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD4, 0x31, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xC5, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0A, 0xC5, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xDA, 0x31, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE0, 0x31, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCB, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x21, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xEC, 0x31, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0A, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0A, 0xE6, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0A, 0x37, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x83, 0x00, 0x00, 0x87, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xF5, 0x31, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x00, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0B, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x10, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x15, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1A, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1F, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x24, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0B, 0xA2, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x29, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x32, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xD7, 0x0A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3B, 0x32, 0x00, 0x00, 0x0A, 0xE6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x44, 0x32, 0x00, 0x00, 0x0A, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x4D, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x51, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0A, 0x55, 0x32, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x5C, 0x32, 0x00, 0x00, 0x08, 0x61, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x66, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6A, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x76, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x82, 0x32, 0x00, 0x80, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8E, 0x32, 0x00, 0x00, 0x0A, 0x97, 0x32, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9B, 0x32, 0x00, 0x00, 0x0A, 0x3B, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xA4, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAC, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xB8, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xC1, 0x32, 0x00, 0xA1, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xE0, 0x0A, 0x00, 0x82, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xE8, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xF0, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xF8, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x08, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x10, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x18, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xEF, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEF, 0x01, 0x00, 0x00, 0x04, 0xEF, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x1F, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x27, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2F, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xE0, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xD3, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xB7, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xBF, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xE8, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xF0, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xF8, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x00, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x08, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x10, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x18, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x09, 0xEF, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0xEF, 0x01, 0x00, 0x00, 0x0A, 0xEF, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x1F, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x27, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0x2F, 0x0B, 0x00, 0x8F, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCA, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD6, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE6, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF2, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFE, 0x32, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x0A, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x15, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x21, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2D, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x39, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x45, 0x33, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x34, 0x07, 0x00, 0x00, 0x0D, 0x8A, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x4F, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5B, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x67, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x73, 0x33, 0x00, 0xC0, 0x4F, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x80, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8E, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9C, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA8, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB4, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xC0, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xCE, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8C, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDC, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE8, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF4, 0x33, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0C, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1B, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x27, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x33, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3F, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x4B, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x57, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x63, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6F, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7B, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x87, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x93, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x9F, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAC, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC5, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD1, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDD, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE9, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF6, 0x34, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x05, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x0B, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x12, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x18, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x27, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x33, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA1, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD8, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x42, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x4E, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFE, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x57, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x65, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x71, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7D, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x86, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8F, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9B, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA7, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB3, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xBF, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC8, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD4, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE0, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEC, 0x35, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF8, 0x35, 0x00, 0x00, 0x05, 0xFC, 0x35, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x05, 0x36, 0x00, 0x97, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x0E, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x1D, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x2C, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x3B, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x4A, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x59, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x68, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x77, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x86, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x95, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xA4, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xB3, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xC2, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF2, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCE, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDA, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE6, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x04, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF2, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFE, 0x36, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0A, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x16, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC0, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x22, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2E, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBB, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEC, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x84, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC7, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0x3B, 0x06, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x00, 0x05, 0x3A, 0x37, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x37, 0x06, 0x00, 0x00, 0x05, 0x43, 0x37, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3F, 0x03, 0x00, 0x00, 0x05, 0x4C, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x19, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x22, 0x02, 0x00, 0x00, 0x05, 0x55, 0x37, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x36, 0x0B, 0x00, 0x00, 0x05, 0x5E, 0x37, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x67, 0x37, 0x00, 0x00, 0x05, 0x6B, 0x37, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3F, 0x03, 0x00, 0x00, 0x05, 0x74, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x0C, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x22, 0x02, 0x00, 0x00, 0x05, 0x7D, 0x37, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x36, 0x0B, 0x00, 0x00, 0x05, 0x86, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF7, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC0, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDF, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x03, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8F, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9B, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA7, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x74, 0x07, 0x00, 0x8B, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB3, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBA, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC6, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCD, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xD9, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE0, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x3A, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xEB, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xF4, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xFD, 0x37, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x06, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x0D, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x14, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x19, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x1E, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x25, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x31, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x38, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x44, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x4B, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x52, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x59, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x65, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6C, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x78, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x84, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x8C, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x94, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x9C, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA4, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xAB, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB2, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xBE, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xC9, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xD4, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xDF, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xEA, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xF2, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xFA, 0x38, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x04, 0x39, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB5, 0x00, 0x00, 0x00, 0x04, 0x3A, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0E, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x1A, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x25, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x43, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x48, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x30, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3C, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x4D, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x52, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x48, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x54, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x60, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6C, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x78, 0x39, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x57, 0x0B, 0x00, 0x00, 0x08, 0x57, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x84, 0x39, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5E, 0x0B, 0x00, 0x00, 0x08, 0x5E, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x90, 0x39, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x43, 0x0B, 0x00, 0x00, 0x08, 0x52, 0x0B, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x4D, 0x0B, 0x00, 0x00, 0x08, 0x48, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x9C, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA3, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xAA, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB1, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC4, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCB, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xD7, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDE, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xEA, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xF5, 0x39, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x00, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x0B, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x16, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x1F, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x28, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2F, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x36, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x42, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x4E, 0x3A, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x55, 0x3A, 0x00, 0x00, 0x07, 0x01, 0x01, 0x00, 0x00, 0x09, 0x01, 0x01, 0x00, 0x00, 0x0B, 0x01, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x5B, 0x3A, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x06, 0x01, 0x01, 0x00, 0x00, 0x08, 0x62, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x68, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x6F, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x76, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7F, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x8B, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x94, 0x3A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA0, 0x3A, 0x00, 0x00, 0x0A, 0xA9, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAE, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBA, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC6, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD2, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xDF, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xEC, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF5, 0x3A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x00, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0B, 0x3B, 0x00, 0x8B, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x18, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x24, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2F, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3B, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x47, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x55, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x08, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x61, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x6D, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x78, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x85, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8E, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xA6, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xAF, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC6, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD4, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xB2, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xB2, 0x00, 0x00, 0x00, 0x06, 0x7D, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x83, 0x00, 0x00, 0x00, 0x06, 0x7D, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xE2, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xF0, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xFE, 0x3B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x65, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x21, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x05, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x11, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1D, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x29, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2F, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x35, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3D, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x46, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x50, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE4, 0x07, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x59, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x66, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x65, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x44, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xBC, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x71, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x59, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7B, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8B, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x9B, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xAB, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBB, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xCB, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDB, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xEB, 0x3C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xFB, 0x3C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x83, 0x00, 0x00, 0x00, 0x0A, 0xE6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE6, 0x00, 0x00, 0x00, 0x0A, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x83, 0x00, 0x00, 0x00, 0x0A, 0x83, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE6, 0x00, 0x00, 0x00, 0x0A, 0xE6, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x83, 0x00, 0x00, 0x00, 0x07, 0xB2, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x22, 0x02, 0x00, 0x00, 0x07, 0xEF, 0x01, 0x00, 0x00, 0x09, 0x22, 0x02, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xE6, 0x00, 0x00, 0x00, 0x07, 0xB2, 0x00, 0x00, 0x00, 0x09, 0xE6, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x83, 0x00, 0x00, 0x00, 0x06, 0x99, 0x00, 0x00, 0x00, 0x09, 0x8D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x99, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x4E, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x0B, 0x3D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x11, 0x3D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x19, 0x3D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x24, 0x3D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x80, 0x00, 0x00, 0x00, 0x07, 0x99, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x99, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x2E, 0x3D, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x99, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x09, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x38, 0x3D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x41, 0x3D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x99, 0x00, 0x00, 0x00, 0x08, 0x99, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x4D, 0x3D, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x99, 0x00, 0x00, 0x00, 0x07, 0x99, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x99, 0x00, 0x00, 0x00, 0x06, 0x99, 0x00, 0x00, 0x00, 0x09, 0x99, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x4E, 0x06, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x09, 0x80, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x58, 0x3D, 0x00, 0x00, 0x08, 0x5C, 0x3D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xB9, 0x05, 0x00, 0x00, 0x08, 0xEE, 0x08, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xB9, 0x05, 0x00, 0x00, 0x08, 0xB2, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0xB2, 0x00, 0x00, 0x00, 0x08, 0xB2, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x05, 0xB2, 0x00, 0x00, 0x00, 0x08, 0xB2, 0x00, 0x00, 0x00, 0x0A, 0x83, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC0, 0x05, 0x00, 0x00, 0x05, 0xB2, 0x00, 0x00, 0x00, 0x08, 0xB2, 0x00, 0x00, 0x00, 0x0A, 0x55, 0x02, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x55, 0x02, 0x00, 0x00, 0x05, 0xB2, 0x00, 0x00, 0x00, 0x08, 0xB2, 0x00, 0x00, 0x00, 0x0A, 0xC0, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x60, 0x3D, 0x00, 0x00, 0x08, 0x64, 0x3D, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x68, 0x3D, 0x00, 0x00, 0x08, 0x6C, 0x3D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x70, 0x3D, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x75, 0x3D, 0x00, 0x00, 0x06, 0x80, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x7A, 0x3D, 0x00, 0x00, 0x06, 0x80, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7E, 0x3D, 0x00, 0x00, 0x06, 0x80, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x3D, 0x00, 0x00, 0x06, 0x80, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x88, 0x3D, 0x00, 0x00, 0x06, 0x80, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x8E, 0x3D, 0x00, 0x00, 0x06, 0x80, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x94, 0x3D, 0x00, 0x00, 0x06, 0x80, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9A, 0x3D, 0x00, 0x00, 0x06, 0x80, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x9F, 0x3D, 0x00, 0x00, 0x05, 0xA4, 0x3D, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xA8, 0x3D, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB2, 0x3D, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x0B, 0x80, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x7D, 0x02, 0x00, 0x00, 0x0A, 0x80, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x84, 0x02, 0x00, 0x00, 0x0A, 0x80, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x7D, 0x02, 0x00, 0x00, 0x09, 0x80, 0x00, 0x00, 0x00, 0x0B, 0x80, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x84, 0x02, 0x00, 0x00, 0x09, 0x80, 0x00, 0x00, 0x00, 0x0B, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xBF, 0x3D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xCB, 0x3D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xD7, 0x3D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xE0, 0x3D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE9, 0x3D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xF5, 0x3D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFE, 0x3D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x09, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x14, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x20, 0x3E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x7D, 0x02, 0x00, 0x00, 0x0A, 0x99, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x84, 0x02, 0x00, 0x00, 0x0A, 0x99, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2C, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3A, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x47, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x53, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x5F, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x6D, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x6B, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x74, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7B, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x87, 0x3E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6B, 0x0B, 0x00, 0x00, 0x0A, 0x99, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x74, 0x0B, 0x00, 0x00, 0x0A, 0x99, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x93, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9E, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x7D, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x85, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xA9, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xB3, 0x3E, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x7D, 0x0B, 0x00, 0x00, 0x0A, 0x80, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x85, 0x0B, 0x00, 0x00, 0x0A, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBD, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC9, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xD5, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xE0, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xEB, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xF5, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xFF, 0x3E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x8D, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x95, 0x0B, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8D, 0x0B, 0x00, 0x00, 0x0A, 0x80, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x95, 0x0B, 0x00, 0x00, 0x0A, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x09, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x13, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x1D, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x26, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x2F, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x38, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x41, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x4A, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x53, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x5C, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x65, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x6E, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x77, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x80, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x89, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x92, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x9D, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA8, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB4, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xC0, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xCB, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xD6, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xE1, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xEC, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xF7, 0x3F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x02, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x0D, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x18, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x23, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x2E, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x37, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x9D, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xA6, 0x0B, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9D, 0x0B, 0x00, 0x00, 0x0A, 0x80, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA6, 0x0B, 0x00, 0x00, 0x0A, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x40, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x45, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x4A, 0x40, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xAF, 0x0B, 0x00, 0x00, 0x07, 0x4F, 0x40, 0x00, 0x00, 0x09, 0xAF, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x52, 0x40, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBC, 0x04, 0x00, 0x00, 0x0B, 0x80, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x04, 0x44, 0x06, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x04, 0xBC, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x5E, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x68, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x44, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xBC, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x72, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x7C, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x86, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x8D, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xD7, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x94, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x9D, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xA6, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xAF, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xB8, 0x40, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x4E, 0x06, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xC1, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xCB, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xD5, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xDF, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xE9, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xF3, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xFD, 0x40, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCB, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x09, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x12, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x1B, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x24, 0x41, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x02, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x09, 0x84, 0x02, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x84, 0x02, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x09, 0x7D, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x06, 0x7D, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x06, 0x84, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2D, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x39, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x45, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x51, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5D, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x69, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x75, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x80, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x8B, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x96, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA1, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAE, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBB, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC6, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD1, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xDE, 0x41, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x00, 0x06, 0x83, 0x00, 0x00, 0x00, 0x0A, 0x83, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x37, 0x06, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x22, 0x02, 0x00, 0x00, 0x06, 0x83, 0x00, 0x00, 0x00, 0x0A, 0x3F, 0x03, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3F, 0x03, 0x00, 0x00, 0x06, 0x83, 0x00, 0x00, 0x00, 0x0A, 0x22, 0x02, 0x00, 0x8D, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xEB, 0x41, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xA8, 0x06, 0x00, 0x84, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF5, 0x41, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x05, 0x42, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x15, 0x42, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x23, 0x42, 0x00, 0x83, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x31, 0x42, 0x00, 0x86, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x38, 0x42, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x42, 0x42, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x4D, 0x42, 0x00, 0x83, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5A, 0x42, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x6A, 0x42, 0x00, 0x86, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x78, 0x42, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x88, 0x42, 0x00, 0xC0, 0x6F, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x98, 0x42, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB3, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xA9, 0x42, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xB9, 0x42, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC5, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xCA, 0x42, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xDA, 0x42, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB3, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xEB, 0x42, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xFB, 0x42, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC5, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0C, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x1C, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x2D, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x3F, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x52, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x4F, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x60, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x72, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x52, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x82, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x94, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA6, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB6, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD7, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0A, 0xDB, 0x0B, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xDB, 0x0B, 0x00, 0x00, 0x08, 0xD7, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC6, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDF, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD6, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x09, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0B, 0xB5, 0x00, 0x00, 0x8F, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE8, 0x43, 0x00, 0xB9, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF4, 0x43, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x00, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0C, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x18, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x24, 0x44, 0x00, 0x94, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0A, 0x30, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x34, 0x44, 0x00, 0x80, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x40, 0x44, 0x00, 0x00, 0x0A, 0x8D, 0x00, 0x00, 0xC0, 0xD8, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x64, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x52, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x49, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x5B, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x5E, 0x44, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x22, 0x04, 0x00, 0x00, 0x05, 0x1C, 0x05, 0x00, 0x00, 0x0B, 0x22, 0x04, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF1, 0x0B, 0x00, 0x00, 0x05, 0x62, 0x44, 0x00, 0x00, 0x0B, 0xF1, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x69, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x6C, 0x44, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x26, 0x02, 0x00, 0x00, 0x04, 0x26, 0x02, 0x00, 0x00, 0x08, 0x26, 0x02, 0x00, 0x00, 0x0C, 0x26, 0x02, 0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC6, 0x04, 0x00, 0x00, 0x04, 0xC6, 0x04, 0x00, 0x00, 0x08, 0xC6, 0x04, 0x00, 0x00, 0x0C, 0xC6, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x70, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x7B, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x86, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x91, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x9C, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xA7, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xB2, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xBD, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC8, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD2, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDD, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE7, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF2, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xFC, 0x44, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x07, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x11, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x1C, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x2E, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x40, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x52, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x64, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x76, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x88, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x9A, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xAC, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBE, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD0, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE2, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF4, 0x45, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x06, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x18, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x2A, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x3C, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x47, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x52, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x5D, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x68, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x73, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x7E, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x89, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x94, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x9E, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xA9, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB4, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xBF, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC9, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD4, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDF, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xEA, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xFC, 0x46, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0E, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x20, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x32, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x44, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x56, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x68, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7A, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8C, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x9E, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB0, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC2, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD4, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE6, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF8, 0x47, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x0A, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x36, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x3B, 0x06, 0x00, 0x00, 0x08, 0x3B, 0x06, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF7, 0x0B, 0x00, 0x00, 0x08, 0xF7, 0x0B, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xB5, 0x00, 0x00, 0x00, 0x08, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x1F, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x2B, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x36, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x42, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x4E, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x59, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x65, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x70, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7A, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x85, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x90, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x9A, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xA5, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB7, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC9, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDB, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xED, 0x48, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xFF, 0x48, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xB5, 0x00, 0x00, 0x00, 0x08, 0x11, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x1B, 0x49, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xB5, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x26, 0x49, 0x00, 0x00, 0x08, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x2F, 0x49, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0A, 0x0C, 0x00, 0x00, 0x08, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x39, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x4B, 0x49, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0A, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x5D, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x68, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x73, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7D, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x87, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x99, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xAB, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xBD, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x15, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xC0, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xC3, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xCE, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x13, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xD2, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x13, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xD6, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDA, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xEC, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF0, 0x49, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x02, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0E, 0x64, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0x0B, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0A, 0x11, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0x19, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x23, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x2F, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3D, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x4D, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x5F, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x71, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x83, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x95, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xA7, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDF, 0x0B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB9, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xCB, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xDD, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xEF, 0x4A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x01, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x64, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x13, 0x4B, 0x00, 0x89, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x25, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x30, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x3B, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x46, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x51, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x5C, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x67, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x72, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x7D, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x88, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x93, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x9A, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xA1, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xA8, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBD, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xCB, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xD3, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xDB, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE4, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0xED, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0xF3, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xF9, 0x4B, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x06, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x13, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x1A, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x21, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x2A, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x33, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3C, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0x45, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0x4B, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x51, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x5E, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x6B, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x72, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x79, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x82, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8B, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x97, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA3, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBB, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC7, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD3, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDF, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEB, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF7, 0x4C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x03, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0F, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1B, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x27, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x33, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3F, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x4B, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x57, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x63, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x75, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x87, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x90, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9B, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA2, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xA9, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xB0, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB7, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xBE, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xC5, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD7, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE9, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xFB, 0x4D, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x0D, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x15, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x21, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2D, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x39, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x45, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x51, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x5C, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x67, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x72, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x7F, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x8A, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x95, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xA0, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAB, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB7, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC3, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCF, 0x4E, 0x00, 0x87, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xDB, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xE6, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xEC, 0x4E, 0x00, 0x81, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xDB, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xF7, 0x4E, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x01, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0C, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x17, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x20, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x2A, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x34, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x3D, 0x4F, 0x00, 0x81, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x49, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x53, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x5D, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x67, 0x4F, 0x00, 0x8B, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x72, 0x4F, 0x00, 0x00, 0x0A, 0x7C, 0x4F, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x83, 0x4F, 0x00, 0x82, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8D, 0x4F, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x99, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xA5, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB0, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xBC, 0x4F, 0x00, 0x81, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC7, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD3, 0x4F, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x57, 0x01, 0x00, 0x00, 0x06, 0x57, 0x01, 0x00, 0x00, 0x0A, 0x57, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x36, 0x01, 0x00, 0x00, 0x06, 0x57, 0x01, 0x00, 0x00, 0x0A, 0x57, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x57, 0x01, 0x00, 0x00, 0x06, 0x36, 0x01, 0x00, 0x00, 0x0A, 0x57, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x36, 0x01, 0x00, 0x00, 0x06, 0x36, 0x01, 0x00, 0x00, 0x0A, 0x57, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x57, 0x01, 0x00, 0x00, 0x06, 0x57, 0x01, 0x00, 0x00, 0x0A, 0x36, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x36, 0x01, 0x00, 0x00, 0x06, 0x57, 0x01, 0x00, 0x00, 0x0A, 0x36, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x57, 0x01, 0x00, 0x00, 0x06, 0x36, 0x01, 0x00, 0x00, 0x0A, 0x36, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x36, 0x01, 0x00, 0x00, 0x06, 0x36, 0x01, 0x00, 0x00, 0x0A, 0x36, 0x01, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDF, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xEB, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF7, 0x4F, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x03, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0E, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x1A, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x26, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x34, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x40, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x4C, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x58, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x67, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x73, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x80, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8E, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9B, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xA8, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB5, 0x50, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC1, 0x50, 0x00, 0x00, 0x08, 0xC7, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xCD, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDB, 0x50, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE9, 0x50, 0x00, 0x00, 0x0A, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF2, 0x50, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x00, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0A, 0x51, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x1E, 0x0C, 0x00, 0x00, 0x08, 0x1E, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x18, 0x51, 0x00, 0x8B, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x25, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x30, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x3A, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x43, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x4E, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x59, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x63, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x6C, 0x51, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x77, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x83, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8F, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x9C, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA9, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB5, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC3, 0x51, 0x00, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xD7, 0x8F, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD1, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xDD, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xE9, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xF5, 0x51, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x01, 0x52, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x0D, 0x52, 0x00, 0xC0, 0x49, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE8, 0x05, 0x00, 0x00, 0x04, 0xED, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE8, 0x05, 0x00, 0x00, 0x04, 0x23, 0x0C, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x0A, 0x7D, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xBA, 0x01, 0x00, 0x00, 0x0A, 0x7D, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x0A, 0x7D, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x0A, 0x7D, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x0A, 0x87, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xBA, 0x01, 0x00, 0x00, 0x0A, 0x87, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x0A, 0x87, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x0A, 0x87, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x0A, 0x87, 0x00, 0x00, 0x00, 0x0C, 0x87, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xBA, 0x01, 0x00, 0x00, 0x0A, 0x87, 0x00, 0x00, 0x00, 0x0C, 0x87, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x0A, 0x87, 0x00, 0x00, 0x00, 0x0C, 0x87, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x0A, 0x87, 0x00, 0x00, 0x00, 0x0C, 0x87, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x7D, 0x00, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x7D, 0x00, 0x00, 0x00, 0x05, 0xBA, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x7D, 0x00, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x7D, 0x00, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x87, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x87, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0xBA, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x87, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x87, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x05, 0xBA, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x00, 0x00, 0x04, 0x98, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x00, 0x00, 0x04, 0x68, 0x06, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x04, 0xCB, 0x04, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x04, 0xD2, 0x04, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x00, 0x00, 0x04, 0x98, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x00, 0x00, 0x04, 0x68, 0x06, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x04, 0xCB, 0x04, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x04, 0xD2, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x10, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x19, 0x52, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x34, 0x02, 0x00, 0x00, 0x0A, 0xB8, 0x00, 0x00, 0x00, 0x0C, 0xB8, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x0A, 0x7D, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x05, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x24, 0x52, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x34, 0x02, 0x00, 0x00, 0x0B, 0xD1, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x0B, 0x87, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xF5, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2F, 0x52, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x34, 0x02, 0x00, 0x00, 0x0A, 0xD1, 0x00, 0x00, 0x00, 0x0C, 0xB8, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x0A, 0x87, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x1B, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3A, 0x52, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x34, 0x02, 0x00, 0x00, 0x0A, 0xD1, 0x00, 0x00, 0x00, 0x0C, 0xD1, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x0A, 0x87, 0x00, 0x00, 0x00, 0x0C, 0x87, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x18, 0x01, 0x00, 0x00, 0x0B, 0x87, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x6F, 0x03, 0x00, 0x00, 0x0B, 0x87, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x63, 0x02, 0x00, 0x00, 0x04, 0x18, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x63, 0x02, 0x00, 0x00, 0x04, 0x6F, 0x03, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0x02, 0x63, 0x02, 0x00, 0x00, 0x04, 0x18, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0x02, 0x63, 0x02, 0x00, 0x00, 0x04, 0x6F, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x45, 0x52, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x00, 0x05, 0x1F, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x04, 0x87, 0x00, 0x00, 0x00, 0x07, 0xD9, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x05, 0x1F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x07, 0xD9, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x31, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x50, 0x52, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2B, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x34, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x5F, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x3D, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x48, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x53, 0x0C, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x5F, 0x03, 0x00, 0x00, 0x0A, 0xAF, 0x00, 0x00, 0x00, 0x0C, 0xAF, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x3D, 0x0C, 0x00, 0x00, 0x0A, 0xAF, 0x00, 0x00, 0x00, 0x0C, 0xAF, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x48, 0x0C, 0x00, 0x00, 0x0A, 0xAF, 0x00, 0x00, 0x00, 0x0C, 0xAF, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x53, 0x0C, 0x00, 0x00, 0x0A, 0x7D, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x44, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x5A, 0x52, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x65, 0x52, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x70, 0x52, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xDE, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x5E, 0x0C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x05, 0xDE, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x07, 0x5E, 0x0C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x4F, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7B, 0x52, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x43, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xA7, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x86, 0x52, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x8D, 0x52, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x66, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x66, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x94, 0x52, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x9C, 0x52, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x71, 0x0A, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0x6F, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA4, 0x52, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6F, 0x06, 0x00, 0x00, 0x08, 0x6F, 0x0C, 0x00, 0xA0, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0x02, 0x3B, 0x0A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0x02, 0xAF, 0x52, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x56, 0x03, 0x00, 0x00, 0x02, 0xB8, 0x52, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x56, 0x03, 0x00, 0x00, 0x02, 0xC1, 0x52, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x63, 0x0A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xCA, 0x52, 0x00, 0x00, 0x06, 0x40, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x79, 0x02, 0x00, 0x00, 0x05, 0x27, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x79, 0x02, 0x00, 0x00, 0x06, 0x40, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0E, 0x06, 0x00, 0x00, 0x05, 0x27, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0E, 0x06, 0x00, 0x00, 0x06, 0x40, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF7, 0x09, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0x27, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x04, 0x87, 0x00, 0x00, 0x00, 0x06, 0x40, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x5A, 0x0A, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x79, 0x02, 0x00, 0x00, 0x06, 0xD1, 0x52, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x14, 0x06, 0x00, 0x00, 0x05, 0x27, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x14, 0x06, 0x00, 0x00, 0x06, 0x40, 0x02, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE6, 0x01, 0x00, 0x00, 0x0D, 0xAF, 0x00, 0x00, 0x00, 0x0F, 0xAF, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0xDA, 0x52, 0x00, 0x00, 0x0F, 0xAF, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x0A, 0x7D, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x0A, 0x7D, 0x00, 0x00, 0x00, 0x0C, 0x7D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x91, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x18, 0x06, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0x76, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x0B, 0x87, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x0B, 0x87, 0x00, 0x00, 0xC0, 0x5A, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xE2, 0x52, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x59, 0x03, 0x00, 0x00, 0x05, 0x1F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x59, 0x03, 0x00, 0x00, 0x05, 0xE6, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xED, 0x52, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF8, 0x52, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0A, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x14, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x1C, 0x53, 0x00, 0xAB, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x59, 0x03, 0x00, 0x00, 0x08, 0x76, 0x03, 0x00, 0xC0, 0x60, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x24, 0x53, 0x00, 0x00, 0x08, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x2C, 0x53, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x37, 0x53, 0x00, 0x00, 0x08, 0xB5, 0x00, 0x00, 0xC0, 0x46, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x3F, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x4A, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x55, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x60, 0x53, 0x00, 0xC0, 0xB1, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x6B, 0x53, 0x00, 0x00, 0x04, 0x6F, 0x53, 0x00, 0xC0, 0x5C, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x09, 0x75, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x09, 0x76, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x09, 0xAF, 0x00, 0x00, 0x80, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x7D, 0x00, 0x00, 0x00, 0x09, 0x75, 0x0C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xAF, 0x00, 0x00, 0x00, 0x09, 0xAF, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x7A, 0x53, 0x00, 0x00, 0x0A, 0xAF, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x59, 0x03, 0x00, 0x00, 0x0A, 0xAF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0xD2, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x80, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x89, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x92, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x9B, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xA4, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xAD, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xB6, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xBD, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xC6, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xCE, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0xD2, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xD5, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xDC, 0x53, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xD2, 0x01, 0x00, 0x00, 0x09, 0xD2, 0x01, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE3, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xEB, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xF5, 0x53, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xFD, 0x53, 0x00, 0x83, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x9D, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x05, 0x54, 0x00, 0x00, 0x08, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x7A, 0x09, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0A, 0x9D, 0x04, 0x00, 0x80, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xA3, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x79, 0x0C, 0x00, 0x00, 0x08, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x54, 0x00, 0x00, 0x08, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x0C, 0xA3, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0xB5, 0x00, 0x00, 0x00, 0x0B, 0x79, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x88, 0x09, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x14, 0x54, 0x00, 0x00, 0x08, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x8E, 0x09, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x65, 0x0B, 0x00, 0x00, 0x08, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xC4, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x1F, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x1B, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x2A, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x26, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x35, 0x09, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x6F, 0x06, 0x00, 0x00, 0x06, 0x40, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xED, 0x05, 0x00, 0x00, 0x0A, 0x7E, 0x0C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x23, 0x0C, 0x00, 0x00, 0x0A, 0x7E, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x31, 0x54, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x3E, 0x54, 0x00, 0x00, 0x08, 0x76, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x44, 0x54, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x6F, 0x06, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xCB, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x4E, 0x54, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x0B, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xBA, 0x01, 0x00, 0x00, 0x0B, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x0B, 0xAF, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x0B, 0x7D, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x63, 0x02, 0x00, 0x00, 0x04, 0x43, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x2E, 0x0A, 0x00, 0x00, 0x03, 0x84, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x42, 0x09, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0xBA, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0xEA, 0x00, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0xBA, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x49, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x56, 0x54, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x34, 0x02, 0x00, 0x00, 0x0B, 0xAF, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x0B, 0x7D, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x66, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x8C, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x34, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x86, 0x04, 0x00, 0x00, 0x04, 0x66, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x86, 0x04, 0x00, 0x00, 0x05, 0x8C, 0x0C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xAF, 0x00, 0x00, 0x00, 0x05, 0x34, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x00, 0x00, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x18, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x6F, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x00, 0x00, 0x00, 0x04, 0x18, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x1F, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0xD9, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x05, 0x1F, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x7D, 0x00, 0x00, 0x00, 0x07, 0xD9, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x71, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x71, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x97, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x07, 0x9C, 0x0C, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x05, 0x71, 0x02, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x04, 0x87, 0x00, 0x00, 0x00, 0x06, 0x71, 0x02, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xB8, 0x00, 0x00, 0x00, 0x03, 0xD1, 0x00, 0x00, 0x00, 0x06, 0x97, 0x0C, 0x00, 0x00, 0x03, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x07, 0x9C, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x2B, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x2B, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE0, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE0, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x00, 0x00, 0x00, 0x04, 0x2B, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xB8, 0x00, 0x00, 0x00, 0x05, 0x2B, 0x02, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x00, 0x00, 0x00, 0x05, 0xE0, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x00, 0x00, 0x00, 0x05, 0xE0, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x54, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x61, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x6A, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x73, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x5D, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7C, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x85, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x8E, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x4A, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xA0, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xAC, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xB2, 0x0C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x56, 0x03, 0x00, 0x00, 0x04, 0x4A, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x04, 0xA0, 0x0C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xAF, 0x00, 0x00, 0x00, 0x05, 0xAC, 0x0C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x05, 0xB2, 0x0C, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x00, 0x00, 0x00, 0x04, 0x98, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x00, 0x00, 0x00, 0x04, 0x68, 0x06, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x04, 0xCB, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x04, 0xD2, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x00, 0x00, 0x04, 0x89, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x00, 0x00, 0x05, 0x97, 0x54, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x87, 0x00, 0x00, 0x00, 0x04, 0xCB, 0x04, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x87, 0x00, 0x00, 0x00, 0x04, 0xD2, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x94, 0x04, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xA1, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x2B, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x34, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0xD9, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xAA, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB7, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC0, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x66, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xC9, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xD3, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xD9, 0x54, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0x7D, 0x00, 0x00, 0x00, 0x05, 0xDE, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xDF, 0x54, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0xAF, 0x00, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x7D, 0x00, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0x43, 0x03, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x84, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x03, 0x72, 0x09, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x04, 0xE8, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x27, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0x40, 0x02, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE6, 0x01, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0x76, 0x03, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0xE6, 0x01, 0x00, 0x00, 0x0E, 0xE5, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0x76, 0x03, 0x00, 0x00, 0x0E, 0xE5, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x05, 0x09, 0x01, 0x00, 0x00, 0x0B, 0x87, 0x00, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x06, 0xF0, 0x00, 0x00, 0x00, 0x0B, 0x87, 0x00, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xF2, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0xFE, 0x54, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x09, 0x55, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x15, 0x55, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x0C, 0x00, 0x00, 0x0B, 0xD3, 0x05, 0x00, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC2, 0x0C, 0x00, 0x00, 0x0B, 0xD3, 0x05, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xB8, 0x0C, 0x00, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x02, 0xC2, 0x0C, 0x00, 0x81, 0x00, 0x02, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x20, 0x55, 0x00, 0x00, 0x0B, 0x2C, 0x55, 0x00, 0xC0, 0xFC, 0x00, 0x01, 0x08, 0x10, 0x08, 0x00, 0x00, 0x01, 0x33, 0x55, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x82, 0x32, 0x4E, 0x46, 0x53}; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_XTFONT_H */ ================================================ FILE: sdk/xtdk/xtfw.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtfw.h * DESCRIPTION: EFI-dependent XT structures * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_XTFW_H #define __XTDK_XTFW_H #include #include /* Version number of the current kernel initialization block */ #define INITIALIZATION_BLOCK_VERSION 1 /* Version number of the current XTOS loader protocol */ #define BOOT_PROTOCOL_VERSION 1 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Memory allocation structures */ typedef enum _LOADER_MEMORY_TYPE { LoaderExceptionBlock, LoaderSystemBlock, LoaderFree, LoaderBad, LoaderLoadedProgram, LoaderFirmwareTemporary, LoaderFirmwarePermanent, LoaderOsloaderHeap, LoaderOsloaderStack, LoaderSystemCode, LoaderHalCode, LoaderBootDriver, LoaderConsoleInDriver, LoaderConsoleOutDriver, LoaderStartupDpcStack, LoaderStartupKernelStack, LoaderStartupPanicStack, LoaderStartupPcrPage, LoaderStartupPdrPage, LoaderRegistryData, LoaderMemoryData, LoaderNlsData, LoaderSpecialMemory, LoaderBBTMemory, LoaderReserve, LoaderXIPRom, LoaderHardwareCachedMemory, LoaderMaximum } LOADER_MEMORY_TYPE, *PLOADER_MEMORY_TYPE; /* Firmware types enumeration list */ typedef enum _SYSTEM_FIRMWARE_TYPE { SystemFirmwareInvalid, SystemFirmwareUnknown, SystemFirmwareEfi, SystemFirmwarePcat } SYSTEM_FIRMWARE_TYPE, *PSYSTEM_FIRMWARE_TYPE; /* PCAT Firmware information block */ typedef struct _PCAT_FIRMWARE_INFORMATION { ULONG PlaceHolder; } PCAT_FIRMWARE_INFORMATION, *PPCAT_FIRMWARE_INFORMATION; /* UEFI Firmware information block */ typedef struct _UEFI_FIRMWARE_INFORMATION { ULONG EfiVersion; PEFI_RUNTIME_SERVICES EfiRuntimeServices; } UEFI_FIRMWARE_INFORMATION, *PUEFI_FIRMWARE_INFORMATION; /* Firmware information block */ typedef struct _FIRMWARE_INFORMATION_BLOCK { SYSTEM_FIRMWARE_TYPE FirmwareType; union { UEFI_FIRMWARE_INFORMATION EfiFirmware; PCAT_FIRMWARE_INFORMATION PcatFirmware; }; } FIRMWARE_INFORMATION_BLOCK, *PFIRMWARE_INFORMATION_BLOCK; /* Boot Loader information block */ typedef struct _LOADER_INFORMATION_BLOCK { PVOID DbgPrint; } LOADER_INFORMATION_BLOCK, *PLOADER_INFORMATION_BLOCK; /* Boot Loader memory mapping information */ typedef struct _LOADER_MEMORY_DESCRIPTOR { LIST_ENTRY ListEntry; LOADER_MEMORY_TYPE MemoryType; ULONG BasePage; ULONG PageCount; } LOADER_MEMORY_DESCRIPTOR, *PLOADER_MEMORY_DESCRIPTOR; /* Loader provided information needed by the kernel to initialize */ typedef struct _KERNEL_INITIALIZATION_BLOCK { ULONG BlockSize; ULONG BlockVersion; ULONG ProtocolVersion; PWCHAR KernelParameters; PFN_NUMBER BootImageSize; LIST_ENTRY LoadOrderListHead; LIST_ENTRY MemoryDescriptorListHead; LIST_ENTRY BootDriverListHead; LIST_ENTRY SystemResourcesListHead; LOADER_INFORMATION_BLOCK LoaderInformation; FIRMWARE_INFORMATION_BLOCK FirmwareInformation; } KERNEL_INITIALIZATION_BLOCK, *PKERNEL_INITIALIZATION_BLOCK; #endif /* __XTOS_ASSEMBLER_ */ #endif /* __XTDK_XTFW_H */ ================================================ FILE: sdk/xtdk/xtglyph.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtglyph.h * DESCRIPTION: XT ASCII glyphs * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_XTGLYPH_H #define __XTDK_XTGLYPH_H #include /* C/C++ specific code */ #ifndef D__XTOS_ASSEMBLER__ CHAR XTGLYPH_EXECTOS_LOGO[] = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x25, 0x23, 0x23, 0x2f, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x28, 0x28, 0x28, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x2f, 0x2f, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x25, 0x25, 0x25, 0x25, 0x25, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x2f, 0x2f, 0x2f, 0x2f, 0x0d, 0x0a, 0x20, 0x20, 0x25, 0x25, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2c, 0x2c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x23, 0x23, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x2f, 0x2f, 0x2c, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x2c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x28, 0x28, 0x2a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x2f, 0x2f, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x25, 0x25, 0x25, 0x25, 0x25, 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x2f, 0x2f, 0x2f, 0x2f, 0x0d, 0x0a, 0x20, 0x20, 0x25, 0x25, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, 0x23, 0x23, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x2f, 0x2f, 0x2a, 0x0d, 0x0a, 0x20, 0x2c, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x25, 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x23, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x28, 0x28, 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x2f, 0x2f, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x20, 0x20, 0x20, 0x20, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x2f, 0x2f, 0x2f, 0x2f, 0x0d, 0x0a, 0x20, 0x20, 0x25, 0x25, 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, 0x23, 0x23, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x2f, 0x2f, 0x2f, 0x0d, 0x0a, 0x20, 0x26, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x0d, 0x0a }; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_XTGLYPH_H */ ================================================ FILE: sdk/xtdk/xtguid.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtguid.h * DESCRIPTION: XTOS Globally Unique Identifiers * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_XTGUID_H #define __XTDK_XTGUID_H /* EFI XT protocols GUIDs */ #define XT_ACPI_PROTOCOL_GUID {0x58544F53, 0x5854, 0x4357, {0x00, 0x00, 0x41, 0x43, 0x50, 0x49, 0x50, 0x54}} #define XT_BOOT_LOADER_PROTOCOL_GUID {0x58544F53, 0x5854, 0x4357, {0x00, 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x50, 0x54}} #define XT_ELF_IMAGE_PROTOCOL_GUID {0x58544F53, 0x5854, 0x4357, {0x45, 0x4C, 0x46, 0x49, 0x4D, 0x47, 0x50, 0x54}} #define XT_FRAMEBUFFER_PROTOCOL_GUID {0x58544F53, 0x5854, 0x4357, {0x00, 0x00, 0x46, 0x42, 0x55, 0x46, 0x50, 0x54}} #define XT_HIVE_IMAGE_PROTOCOL_GUID {0x58544F53, 0x5854, 0x4357, {0x48, 0x49, 0x56, 0x49, 0x4D, 0x47, 0x50, 0x54}} #define XT_PECOFF_IMAGE_PROTOCOL_GUID {0x58544F53, 0x5854, 0x4357, {0x00, 0x50, 0x45, 0x49, 0x4D, 0x47, 0x50, 0x54}} /* EFI XT boot protocols GUIDs */ #define XT_CHAIN_BOOT_PROTOCOL_GUID {0x58544F53, 0x5854, 0x4357, {0x00, 0x43, 0x48, 0x41, 0x49, 0x4E, 0x50, 0x54}} #define XT_DUMMY_BOOT_PROTOCOL_GUID {0x58544F53, 0x5854, 0x4357, {0x00, 0x44, 0x55, 0x4D, 0x4D, 0x59, 0x50, 0x54}} #define XT_LINUX_BOOT_PROTOCOL_GUID {0x58544F53, 0x5854, 0x4357, {0x00, 0x4C, 0x49, 0x4E, 0x55, 0x58, 0x50, 0x54}} #define XT_WINNT_BOOT_PROTOCOL_GUID {0x58544F53, 0x5854, 0x4357, {0x00, 0x57, 0x49, 0x4E, 0x4E, 0x54, 0x50, 0x54}} #define XT_XTOS_BOOT_PROTOCOL_GUID {0x58544F53, 0x5854, 0x4357, {0x00, 0x00, 0x58, 0x54, 0x4F, 0x53, 0x50, 0x54}} /* XTOS GUIDs */ #define XTOS_EXECTOS_GUID {0x58544F53, 0x5854, 0x4357, {0x00, 0x45, 0x58, 0x45, 0x43, 0x54, 0x4F, 0x53}} #define XTOS_XTLDR_LOADER_GUID {0x58544F53, 0x5854, 0x4357, {0x00, 0x00, 0x00, 0x58, 0x54, 0x4C, 0x44, 0x52}} #endif /* __XTDK_XTGUID_H */ ================================================ FILE: sdk/xtdk/xtimage.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtimage.h * DESCRIPTION: Executable image structures definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_XTIMAGE_H #define __XTDK_XTIMAGE_H #include #include #include #include /* PE/COFF file image signatures */ #define PECOFF_IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */ #define PECOFF_IMAGE_OS2_SIGNATURE 0x454E /* NE */ #define PECOFF_IMAGE_OS2LE_SIGNATURE 0x454C /* LE */ #define PECOFF_IMAGE_VXD_SIGNATURE 0x454C /* LE */ #define PECOFF_IMAGE_EDOS_SIGNATURE 0x44454550 /* PEED */ #define PECOFF_IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */ #define PECOFF_IMAGE_XT_SIGNATURE 0x54584550 /* PEXT */ /* PE/COFF image subsystems */ #define PECOFF_IMAGE_SUBSYSTEM_UNKNOWN 0 #define PECOFF_IMAGE_SUBSYSTEM_NATIVE 1 #define PECOFF_IMAGE_SUBSYSTEM_WINDOWS_GUI 2 #define PECOFF_IMAGE_SUBSYSTEM_WINDOWS_CUI 3 #define PECOFF_IMAGE_SUBSYSTEM_WINDOWS_CE_OLD 4 #define PECOFF_IMAGE_SUBSYSTEM_OS2_CUI 5 #define PECOFF_IMAGE_SUBSYSTEM_POSIX_CUI 7 #define PECOFF_IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 #define PECOFF_IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 #define PECOFF_IMAGE_SUBSYSTEM_EFI_APPLICATION 10 #define PECOFF_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 #define PECOFF_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 #define PECOFF_IMAGE_SUBSYSTEM_EFI_ROM 13 #define PECOFF_IMAGE_SUBSYSTEM_XBOX 14 #define PECOFF_IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16 #define PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_KERNEL 20 #define PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_APPLICATION 21 #define PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_DRIVER 22 #define PECOFF_IMAGE_SUBSYSTEM_XT_DYNAMIC_LIBRARY 23 #define PECOFF_IMAGE_SUBSYSTEM_XT_APPLICATION_CLI 24 #define PECOFF_IMAGE_SUBSYSTEM_XT_APPLICATION_GDI 25 /* PE/COFF file image architecture */ #define PECOFF_IMAGE_FILE_MACHINE_UNKNOWN 0x0000 #define PECOFF_IMAGE_FILE_MACHINE_I386 0x014C #define PECOFF_IMAGE_FILE_MACHINE_R4000 0x0166 #define PECOFF_IMAGE_FILE_MACHINE_R3000 0x0162 #define PECOFF_IMAGE_FILE_MACHINE_R10000 0x0168 #define PECOFF_IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 #define PECOFF_IMAGE_FILE_MACHINE_ALPHA 0x0184 #define PECOFF_IMAGE_FILE_MACHINE_SH3 0x01A2 #define PECOFF_IMAGE_FILE_MACHINE_SH3DSP 0x01A3 #define PECOFF_IMAGE_FILE_MACHINE_SH3E 0x01A4 #define PECOFF_IMAGE_FILE_MACHINE_SH4 0x01A6 #define PECOFF_IMAGE_FILE_MACHINE_SH5 0x01A8 #define PECOFF_IMAGE_FILE_MACHINE_ARM 0x01C0 #define PECOFF_IMAGE_FILE_MACHINE_THUMB 0x01C2 #define PECOFF_IMAGE_FILE_MACHINE_AM33 0x01D3 #define PECOFF_IMAGE_FILE_MACHINE_POWERPC 0x01F0 #define PECOFF_IMAGE_FILE_MACHINE_POWERPCFP 0x01F1 #define PECOFF_IMAGE_FILE_MACHINE_IA64 0x0200 #define PECOFF_IMAGE_FILE_MACHINE_MIPS16 0x0266 #define PECOFF_IMAGE_FILE_MACHINE_ALPHA64 0x0284 #define PECOFF_IMAGE_FILE_MACHINE_MIPSFPU 0x0366 #define PECOFF_IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 #define PECOFF_IMAGE_FILE_MACHINE_AXP64 0x0284 #define PECOFF_IMAGE_FILE_MACHINE_TRICORE 0x0520 #define PECOFF_IMAGE_FILE_MACHINE_CEF 0x0CEF #define PECOFF_IMAGE_FILE_MACHINE_EBC 0x0EBC #define PECOFF_IMAGE_FILE_MACHINE_AMD64 0x8664 #define PECOFF_IMAGE_FILE_MACHINE_M32R 0x9041 #define PECOFF_IMAGE_FILE_MACHINE_CEE 0xC0EE /* PE/COFF image characteristic attributes */ #define PECOFF_IMAGE_FILE_RELOCS_STRIPPED 0x0001 #define PECOFF_IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 #define PECOFF_IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 #define PECOFF_IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 #define PECOFF_IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 #define PECOFF_IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 #define PECOFF_IMAGE_FILE_BYTES_REVERSED_LO 0x0080 #define PECOFF_IMAGE_FILE_32BIT_MACHINE 0x0100 #define PECOFF_IMAGE_FILE_DEBUG_STRIPPED 0x0200 #define PECOFF_IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 #define PECOFF_IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 #define PECOFF_IMAGE_FILE_SYSTEM 0x1000 #define PECOFF_IMAGE_FILE_DLL 0x2000 #define PECOFF_IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 #define PECOFF_IMAGE_FILE_BYTES_REVERSED_HI 0x8000 /* PE/COFF directory entries count */ #define PECOFF_IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 /* PE/COFF image HDR magic */ #define PECOFF_IMAGE_PE_OPTIONAL_HDR32_MAGIC 0x10B #define PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC 0x20B #define PECOFF_IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 /* PE/COFF image characteristics */ #define PECOFF_IMAGE_CHARACTERISTICS_HIGH_ENTROPY_VA 0x0020 #define PECOFF_IMAGE_CHARACTERISTICS_DYNAMIC_BASE 0x0040 #define PECOFF_IMAGE_CHARACTERISTICS_FORCE_INTEGRITY 0x0080 #define PECOFF_IMAGE_CHARACTERISTICS_NX_COMPAT 0x0100 #define PECOFF_IMAGE_CHARACTERISTICS_NO_ISOLATION 0x0200 #define PECOFF_IMAGE_CHARACTERISTICS_NO_SEH 0x0400 #define PECOFF_IMAGE_CHARACTERISTICS_NO_BIND 0x0800 #define PECOFF_IMAGE_CHARACTERISTICS_APPCONTAINER 0x1000 #define PECOFF_IMAGE_CHARACTERISTICS_WDM_DRIVER 0x2000 #define PECOFF_IMAGE_CHARACTERISTICS_GUARD_CF 0x4000 #define PECOFF_IMAGE_CHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 /* PE/COFF directory entries */ #define PECOFF_IMAGE_DIRECTORY_ENTRY_EXPORT 0x0 #define PECOFF_IMAGE_DIRECTORY_ENTRY_IMPORT 0x1 #define PECOFF_IMAGE_DIRECTORY_ENTRY_RESOURCE 0x2 #define PECOFF_IMAGE_DIRECTORY_ENTRY_EXCEPTION 0x3 #define PECOFF_IMAGE_DIRECTORY_ENTRY_SECURITY 0x4 #define PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC 0x5 #define PECOFF_IMAGE_DIRECTORY_ENTRY_DEBUG 0x6 #define PECOFF_IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 0x7 #define PECOFF_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 0x8 #define PECOFF_IMAGE_DIRECTORY_ENTRY_TLS 0x9 #define PECOFF_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 0xA #define PECOFF_IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 0xB #define PECOFF_IMAGE_DIRECTORY_ENTRY_IAT 0xC #define PECOFF_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 0xD #define PECOFF_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 0xE /* PE/COFF image relocation types */ #define PECOFF_IMAGE_REL_BASED_ABSOLUTE 0x0 #define PECOFF_IMAGE_REL_BASED_HIGH 0x1 #define PECOFF_IMAGE_REL_BASED_LOW 0x2 #define PECOFF_IMAGE_REL_BASED_HIGHLOW 0x3 #define PECOFF_IMAGE_REL_BASED_HIGHADJ 0x4 #define PECOFF_IMAGE_REL_BASED_MIPS_JMPADDR 0x5 #define PECOFF_IMAGE_REL_BASED_SECTION 0x6 #define PECOFF_IMAGE_REL_BASED_REL32 0x7 #define PECOFF_IMAGE_REL_BASED_VXD_RELATIVE 0x8 #define PECOFF_IMAGE_REL_BASED_MIPS_JMPADDR16 0x9 #define PECOFF_IMAGE_REL_BASED_IA64_IMM64 0x9 #define PECOFF_IMAGE_REL_BASED_DIR64 0xA /* PE/COFF related sizes */ #define PECOFF_IMAGE_SIZEOF_SHORT_NAME 8 #define PECOFF_IMAGE_SIZEOF_BASE_RELOCATION 8 #define PECOFF_IMAGE_SIZEOF_SECTION_HEADER 40 #define PECOFF_IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56 #define PECOFF_IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28 #define PECOFF_IMAGE_SIZEOF_PE_OPTIONAL32_HEADER 224 #define PECOFF_IMAGE_SIZEOF_PE_OPTIONAL64_HEADER 240 /* PE/COFF image section characteristics */ #define PECOFF_IMAGE_SCN_TYPE_REG 0x00000000 #define PECOFF_IMAGE_SCN_TYPE_DSECT 0x00000001 #define PECOFF_IMAGE_SCN_TYPE_NOLOAD 0x00000002 #define PECOFF_IMAGE_SCN_TYPE_GROUP 0x00000004 #define PECOFF_IMAGE_SCN_TYPE_NO_PAD 0x00000008 #define PECOFF_IMAGE_SCN_TYPE_COPY 0x00000010 #define PECOFF_IMAGE_SCN_CNT_CODE 0x00000020 #define PECOFF_IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 #define PECOFF_IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 #define PECOFF_IMAGE_SCN_LNK_OTHER 0x00000100 #define PECOFF_IMAGE_SCN_LNK_INFO 0x00000200 #define PECOFF_IMAGE_SCN_TYPE_OVER 0x00000400 #define PECOFF_IMAGE_SCN_LNK_REMOVE 0x00000800 #define PECOFF_IMAGE_SCN_LNK_COMDAT 0x00001000 #define PECOFF_IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 #define PECOFF_IMAGE_SCN_GPREL 0x00008000 #define PECOFF_IMAGE_SCN_MEM_FARDATA 0x00008000 #define PECOFF_IMAGE_SCN_MEM_PURGEABLE 0x00020000 #define PECOFF_IMAGE_SCN_MEM_16BIT 0x00020000 #define PECOFF_IMAGE_SCN_MEM_LOCKED 0x00040000 #define PECOFF_IMAGE_SCN_MEM_PRELOAD 0x00080000 #define PECOFF_IMAGE_SCN_ALIGN_1BYTES 0x00100000 #define PECOFF_IMAGE_SCN_ALIGN_2BYTES 0x00200000 #define PECOFF_IMAGE_SCN_ALIGN_4BYTES 0x00300000 #define PECOFF_IMAGE_SCN_ALIGN_8BYTES 0x00400000 #define PECOFF_IMAGE_SCN_ALIGN_16BYTES 0x00500000 #define PECOFF_IMAGE_SCN_ALIGN_32BYTES 0x00600000 #define PECOFF_IMAGE_SCN_ALIGN_64BYTES 0x00700000 #define PECOFF_IMAGE_SCN_ALIGN_128BYTES 0x00800000 #define PECOFF_IMAGE_SCN_ALIGN_256BYTES 0x00900000 #define PECOFF_IMAGE_SCN_ALIGN_512BYTES 0x00A00000 #define PECOFF_IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 #define PECOFF_IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 #define PECOFF_IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 #define PECOFF_IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 #define PECOFF_IMAGE_SCN_ALIGN_MASK 0x00F00000 #define PECOFF_IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 #define PECOFF_IMAGE_SCN_MEM_DISCARDABLE 0x02000000 #define PECOFF_IMAGE_SCN_MEM_NOT_CACHED 0x04000000 #define PECOFF_IMAGE_SCN_MEM_NOT_PAGED 0x08000000 #define PECOFF_IMAGE_SCN_MEM_SHARED 0x10000000 #define PECOFF_IMAGE_SCN_MEM_EXECUTE 0x20000000 #define PECOFF_IMAGE_SCN_MEM_READ 0x40000000 #define PECOFF_IMAGE_SCN_MEM_WRITE 0x80000000 /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* PE/COFF image representation structure */ typedef struct _PECOFF_IMAGE_CONTEXT { PPECOFF_IMAGE_DOS_HEADER DosHeader; PPECOFF_IMAGE_PE_HEADER PeHeader; PVOID Data; UINT64 FileSize; UINT ImagePages; UINT ImageSize; LOADER_MEMORY_TYPE MemoryType; PVOID PhysicalAddress; PVOID VirtualAddress; } PECOFF_IMAGE_CONTEXT, *PPECOFF_IMAGE_CONTEXT; /* PE/COFF directory format */ typedef struct _PECOFF_IMAGE_DATA_DIRECTORY { ULONG VirtualAddress; ULONG Size; } PECOFF_IMAGE_DATA_DIRECTORY, *PPECOFF_IMAGE_DATA_DIRECTORY; /* PE file image header */ typedef struct _PECOFF_IMAGE_FILE_HEADER { USHORT Machine; USHORT NumberOfSections; ULONG TimeDateStamp; ULONG PointerToSymbolTable; ULONG NumberOfSymbols; USHORT SizeOfOptionalHeader; USHORT Characteristics; } PECOFF_IMAGE_FILE_HEADER, *PPECOFF_IMAGE_FILE_HEADER; /* DOS PE image header */ typedef struct _PECOFF_IMAGE_DOS_HEADER { USHORT Magic; USHORT LastPageBytes; USHORT ImagePages; USHORT Relocations; USHORT HeaderParagraphs; USHORT MinExtraParagraphs; USHORT MaxExtraParagraphs; USHORT InitialSS; USHORT InitialSP; USHORT Checksum; USHORT InitialIP; USHORT InitialCS; USHORT RelocationTableOffset; USHORT OverlayNumber; USHORT Reserved1[4]; USHORT OemIdentification; USHORT OemInformation; USHORT Reserved2[10]; LONG PeHeaderOffset; } PECOFF_IMAGE_DOS_HEADER, *PPECOFF_IMAGE_DOS_HEADER; /* OS/2 PE image header */ typedef struct _PECOFF_IMAGE_OS2_HEADER { USHORT Magic; CHAR MajorVersion; CHAR MinorVersion; USHORT EntryTableOffset; USHORT EntryTableLength; LONG FileLoadCRC; UCHAR ProgFlags; UCHAR ApplFlags; USHORT AutoDataSegIndex; USHORT InitHeapSize; USHORT InitStackSize; LONG EntryPoint; LONG InitStack; USHORT SegCount; USHORT ModRefs; USHORT NoResNamesTabSiz; USHORT SegTableOffset; USHORT ResTableOffset; USHORT ResidNamTable; USHORT ModRefTable; USHORT ImportNameTable; LONG NonResTabableOffset; USHORT MovEntryCount; USHORT ImageAlignment; USHORT ResTableEntries; UCHAR ImageType; UCHAR ImageFlags; USHORT ReturnThunkOffset; USHORT ReferenceThunksOffset; USHORT SwapArea; USHORT WindowsVersion; } PECOFF_IMAGE_OS2_HEADER, *PPECOFF_IMAGE_OS2_HEADER; /* Windows VXD PE image header */ typedef struct _PECOFF_IMAGE_VXD_HEADER { USHORT Magic; UCHAR BytesOrder; UCHAR WordsOrder; ULONG FormatLevel; USHORT CpuType; USHORT OSType; ULONG ModuleVersion; ULONG ModuleFlags; ULONG ModulePages; ULONG EntryPoint; ULONG Eip; ULONG Stack; ULONG Esp; ULONG PageSize; ULONG LastPageSize; ULONG FixupSectionSize; ULONG FixupSectionChecksum; ULONG LoaderSectionSize; ULONG LoaderSectionChecksum; ULONG ObjectTableOffset; ULONG NumberOfObjects; ULONG ObjectPageMapOffset; ULONG ObjectIterMapOffset; ULONG ResTableOffset; ULONG NumberOfResources; ULONG ResidentTableOffset; ULONG EntryTableOffset; ULONG DirectiveTableOffset; ULONG NumberOfDirectives; ULONG FixupPageTableOffset; ULONG FixupRecordTableOffset; ULONG ImportTableOffset; ULONG NumberOfImports; ULONG ImportProcTableOffset; ULONG PageChecksumTableOffset; ULONG DataPagesOffset; ULONG NumberOfPreloadPages; ULONG NonResidentTableOffset; ULONG NonResidentTableSize; ULONG NonResidentTableChecksum; ULONG AutoDataObject; ULONG DebugInfoOffset; ULONG DebugInfoLength; ULONG PreLoadSectionPages; ULONG DemandLoadSectionPages; ULONG HeapSize; UCHAR Reserved[12]; ULONG WinResOffset; ULONG WinResLength; USHORT DeviceId; USHORT DDKVersion; } PECOFF_IMAGE_VXD_HEADER, *PPECOFF_IMAGE_VXD_HEADER; /* PE/COFF section header */ typedef struct _PECOFF_IMAGE_SECTION_HEADER { UCHAR Name[PECOFF_IMAGE_SIZEOF_SHORT_NAME]; union { ULONG PhysicalAddress; ULONG VirtualSize; } Misc; ULONG VirtualAddress; ULONG SizeOfRawData; ULONG PointerToRawData; ULONG PointerToRelocations; ULONG PointerToLinenumbers; USHORT NumberOfRelocations; USHORT NumberOfLinenumbers; ULONG Characteristics; } PECOFF_IMAGE_SECTION_HEADER, *PPECOFF_IMAGE_SECTION_HEADER; /* PE/COFF image 32bit optional header */ typedef struct _PECOFF_IMAGE_OPTIONAL_HEADER32 { USHORT Magic; UCHAR MajorLinkerVersion; UCHAR MinorLinkerVersion; ULONG SizeOfCode; ULONG SizeOfInitializedData; ULONG SizeOfUninitializedData; ULONG AddressOfEntryPoint; ULONG BaseOfCode; ULONG BaseOfData; ULONG ImageBase; ULONG SectionAlignment; ULONG FileAlignment; USHORT MajorOperatingSystemVersion; USHORT MinorOperatingSystemVersion; USHORT MajorImageVersion; USHORT MinorImageVersion; USHORT MajorSubsystemVersion; USHORT MinorSubsystemVersion; ULONG Win32VersionValue; ULONG SizeOfImage; ULONG SizeOfHeaders; ULONG CheckSum; USHORT Subsystem; USHORT DllCharacteristics; ULONG SizeOfStackReserve; ULONG SizeOfStackCommit; ULONG SizeOfHeapReserve; ULONG SizeOfHeapCommit; ULONG LoaderFlags; ULONG NumberOfRvaAndSizes; PECOFF_IMAGE_DATA_DIRECTORY DataDirectory[PECOFF_IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } PECOFF_IMAGE_OPTIONAL_HEADER32, *PPECOFF_IMAGE_OPTIONAL_HEADER32; /* PE/COFF image 32bit optional header */ typedef struct _PECOFF_IMAGE_OPTIONAL_HEADER64 { USHORT Magic; UCHAR MajorLinkerVersion; UCHAR MinorLinkerVersion; ULONG SizeOfCode; ULONG SizeOfInitializedData; ULONG SizeOfUninitializedData; ULONG AddressOfEntryPoint; ULONG BaseOfCode; ULONGLONG ImageBase; ULONG SectionAlignment; ULONG FileAlignment; USHORT MajorOperatingSystemVersion; USHORT MinorOperatingSystemVersion; USHORT MajorImageVersion; USHORT MinorImageVersion; USHORT MajorSubsystemVersion; USHORT MinorSubsystemVersion; ULONG Win32VersionValue; ULONG SizeOfImage; ULONG SizeOfHeaders; ULONG CheckSum; USHORT Subsystem; USHORT DllCharacteristics; ULONGLONG SizeOfStackReserve; ULONGLONG SizeOfStackCommit; ULONGLONG SizeOfHeapReserve; ULONGLONG SizeOfHeapCommit; ULONG LoaderFlags; ULONG NumberOfRvaAndSizes; PECOFF_IMAGE_DATA_DIRECTORY DataDirectory[PECOFF_IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } PECOFF_IMAGE_OPTIONAL_HEADER64, *PPECOFF_IMAGE_OPTIONAL_HEADER64; /* PE/COFF ROM optional header */ typedef struct _PECOFF_IMAGE_ROM_OPTIONAL_HEADER { USHORT Magic; UCHAR MajorLinkerVersion; UCHAR MinorLinkerVersion; ULONG SizeOfCode; ULONG SizeOfInitializedData; ULONG SizeOfUninitializedData; ULONG AddressOfEntryPoint; ULONG BaseOfCode; ULONG BaseOfData; ULONG BaseOfBss; ULONG GprMask; ULONG CprMask[4]; ULONG GpValue; } PECOFF_IMAGE_ROM_OPTIONAL_HEADER, *PPECOFF_IMAGE_ROM_OPTIONAL_HEADER; /* PE/COFF PE image header */ typedef struct _PECOFF_IMAGE_PE_HEADER { ULONG Signature; PECOFF_IMAGE_FILE_HEADER FileHeader; union { PECOFF_IMAGE_OPTIONAL_HEADER32 OptionalHeader32; PECOFF_IMAGE_OPTIONAL_HEADER64 OptionalHeader64; }; } PECOFF_IMAGE_PE_HEADER, *PPECOFF_IMAGE_PE_HEADER; /* PE/COFF ROM image header */ typedef struct _PECOFF_IMAGE_ROM_HEADER { PECOFF_IMAGE_FILE_HEADER FileHeader; PECOFF_IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; } PECOFF_IMAGE_ROM_HEADER, *PPECOFF_IMAGE_ROM_HEADER; /* PE/COFF based relocation format */ typedef struct _PECOFF_IMAGE_BASE_RELOCATION { ULONG VirtualAddress; ULONG SizeOfBlock; } PECOFF_IMAGE_BASE_RELOCATION, *PPECOFF_IMAGE_BASE_RELOCATION; /* PE/COFF image load config code integrity */ typedef struct _PECOFF_IMAGE_LOAD_CONFIG_CODE_INTEGRITY { USHORT Flags; USHORT Catalog; ULONG CatalogOffset; ULONG Reserved; } PECOFF_IMAGE_LOAD_CONFIG_CODE_INTEGRITY, *PPECOFF_IMAGE_LOAD_CONFIG_CODE_INTEGRITY; /* 32-bit load configuration directory */ typedef struct _PECOFF_IMAGE_LOAD_CONFIG_DIRECTORY32 { ULONG Size; ULONG TimeDateStamp; USHORT MajorVersion; USHORT MinorVersion; ULONG GlobalFlagsClear; ULONG GlobalFlagsSet; ULONG CriticalSectionDefaultTimeout; ULONG DeCommitFreeBlockThreshold; ULONG DeCommitTotalFreeThreshold; ULONG LockPrefixTable; ULONG MaximumAllocationSize; ULONG VirtualMemoryThreshold; ULONG ProcessHeapFlags; ULONG ProcessAffinityMask; USHORT CSDVersion; USHORT Reserved1; ULONG EditList; ULONG SecurityCookie; ULONG SEHandlerTable; ULONG SEHandlerCount; } PECOFF_IMAGE_LOAD_CONFIG_DIRECTORY32, *PPECOFF_IMAGE_LOAD_CONFIG_DIRECTORY32; /* 64-bit load configuration directory */ typedef struct _PECOFF_IMAGE_LOAD_CONFIG_DIRECTORY64 { ULONG Size; ULONG TimeDateStamp; USHORT MajorVersion; USHORT MinorVersion; ULONG GlobalFlagsClear; ULONG GlobalFlagsSet; ULONG CriticalSectionDefaultTimeout; ULONGLONG DeCommitFreeBlockThreshold; ULONGLONG DeCommitTotalFreeThreshold; ULONGLONG LockPrefixTable; ULONGLONG MaximumAllocationSize; ULONGLONG VirtualMemoryThreshold; ULONGLONG ProcessAffinityMask; ULONG ProcessHeapFlags; USHORT CSDVersion; USHORT DependentLoadFlags; ULONGLONG EditList; ULONGLONG SecurityCookie; ULONGLONG SEHandlerTable; ULONGLONG SEHandlerCount; ULONGLONG GuardCFCheckFunctionPointer; ULONGLONG GuardCFDispatchFunctionPointer; ULONGLONG GuardCFFunctionTable; ULONGLONG GuardCFFunctionCount; ULONG GuardFlags; PECOFF_IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; ULONGLONG GuardAddressTakenIatEntryTable; ULONGLONG GuardAddressTakenIatEntryCount; ULONGLONG GuardLongJumpTargetTable; ULONGLONG GuardLongJumpTargetCount; ULONGLONG DynamicValueRelocTable; ULONGLONG CHPEMetadataPointer; ULONGLONG GuardRFFailureRoutine; ULONGLONG GuardRFFailureRoutineFunctionPointer; ULONG DynamicValueRelocTableOffset; USHORT DynamicValueRelocTableSection; USHORT Reserved2; ULONGLONG GuardRFVerifyStackPointerFunctionPointer; ULONG HotPatchTableOffset; ULONG Reserved3; ULONGLONG EnclaveConfigurationPointer; ULONGLONG VolatileMetadataPointer; } PECOFF_IMAGE_LOAD_CONFIG_DIRECTORY64, *PPECOFF_IMAGE_LOAD_CONFIG_DIRECTORY64; /* PE/COFF image import descriptor */ typedef struct _PECOFF_IMAGE_IMPORT_DESCRIPTOR { union { ULONG Characteristics; ULONG OriginalFirstThunk; }; ULONG TimeDateStamp; ULONG ForwarderChain; ULONG Name; ULONG FirstThunk; } PECOFF_IMAGE_IMPORT_DESCRIPTOR, *PPECOFF_IMAGE_IMPORT_DESCRIPTOR; /* PE/COFF image export directory */ typedef struct _PECOFF_IMAGE_EXPORT_DIRECTORY { ULONG Characteristics; ULONG TimeDateStamp; USHORT MajorVersion; USHORT MinorVersion; ULONG Name; ULONG Base; ULONG NumberOfFunctions; ULONG NumberOfNames; ULONG AddressOfFunctions; ULONG AddressOfNames; ULONG AddressOfNameOrdinals; } PECOFF_IMAGE_EXPORT_DIRECTORY, *PPECOFF_IMAGE_EXPORT_DIRECTORY; /* PE/COFF image resource directory */ typedef struct _PECOFF_IMAGE_RESOURCE_DIRECTORY { ULONG Characteristics; ULONG TimeDateStamp; USHORT MajorVersion; USHORT MinorVersion; USHORT NumberOfNamedEntries; USHORT NumberOfIdEntries; } PECOFF_IMAGE_RESOURCE_DIRECTORY, *PPECOFF_IMAGE_RESOURCE_DIRECTORY; /* PE/COFF image resource directory entry */ typedef struct _PECOFF_IMAGE_RESOURCE_DIRECTORY_ENTRY { union { struct { ULONG NameOffset:31; ULONG NameIsString:1; }; ULONG Name; USHORT Id; }; union { ULONG OffsetToData; struct { ULONG OffsetToDirectory:31; ULONG DataIsDirectory:1; }; }; } PECOFF_IMAGE_RESOURCE_DIRECTORY_ENTRY, *PPECOFF_IMAGE_RESOURCE_DIRECTORY_ENTRY; /* PE/COFF image resource data entry */ typedef struct _PECOFF_IMAGE_RESOURCE_DATA_ENTRY { ULONG OffsetToData; ULONG Size; ULONG CodePage; ULONG Reserved; } PECOFF_IMAGE_RESOURCE_DATA_ENTRY, *PPECOFF_IMAGE_RESOURCE_DATA_ENTRY; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_XTIMAGE_H */ ================================================ FILE: sdk/xtdk/xtkmapi.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtkmapi.h * DESCRIPTION: Top level header for the kernel-mode XT API * DEVELOPERS: Rafal Kupiec */ /* Base XT headers */ #include #include #include #include #include /* XT forward references */ #include /* Architecture-specific XT forward references */ #include ARCH_HEADER(xtstruct.h) /* Architecture-independent XT API */ #include #include #include #include #include #include /* Low level data types headers */ #include #include #include #include #include #include #include #include #include #include /* Architecture-specific low level data types headers */ #include ARCH_HEADER(artypes.h) #include ARCH_HEADER(hltypes.h) #include ARCH_HEADER(ketypes.h) #include ARCH_HEADER(mmtypes.h) /* XT routines */ #include #include #include #include #include #include /* Architecture specific XT routines */ #include ARCH_HEADER(hlfuncs.h) ================================================ FILE: sdk/xtdk/xtstatus.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtstatus.h * DESCRIPTION: Status code definitions for the XT API * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_XTSTATUS_H #define __XTDK_XTSTATUS_H /* EFI status code definitions */ #define STATUS_EFI_SUCCESS (EFI_ERROR_MASK & 0x00) #define STATUS_EFI_LOAD_ERROR (EFI_ERROR_MASK | 0x01) #define STATUS_EFI_INVALID_PARAMETER (EFI_ERROR_MASK | 0x02) #define STATUS_EFI_UNSUPPORTED (EFI_ERROR_MASK | 0x03) #define STATUS_EFI_BAD_BUFFER_SIZE (EFI_ERROR_MASK | 0x04) #define STATUS_EFI_BUFFER_TOO_SMALL (EFI_ERROR_MASK | 0x05) #define STATUS_EFI_NOT_READY (EFI_ERROR_MASK | 0x06) #define STATUS_EFI_DEVICE_ERROR (EFI_ERROR_MASK | 0x07) #define STATUS_EFI_WRITE_PROTECTED (EFI_ERROR_MASK | 0x08) #define STATUS_EFI_OUT_OF_RESOURCES (EFI_ERROR_MASK | 0x09) #define STATUS_EFI_VOLUME_CORRUPTED (EFI_ERROR_MASK | 0x0A) #define STATUS_EFI_VOLUME_FULL (EFI_ERROR_MASK | 0x0B) #define STATUS_EFI_NO_MEDIA (EFI_ERROR_MASK | 0x0C) #define STATUS_EFI_MEDIA_CHANGED (EFI_ERROR_MASK | 0x0D) #define STATUS_EFI_NOT_FOUND (EFI_ERROR_MASK | 0x0E) #define STATUS_EFI_ACCESS_DENIED (EFI_ERROR_MASK | 0x0F) #define STATUS_EFI_NO_RESPONSE (EFI_ERROR_MASK | 0x10) #define STATUS_EFI_NO_MAPPING (EFI_ERROR_MASK | 0x11) #define STATUS_EFI_TIMEOUT (EFI_ERROR_MASK | 0x12) #define STATUS_EFI_NOT_STARTED (EFI_ERROR_MASK | 0x13) #define STATUS_EFI_ALREADY_STARTED (EFI_ERROR_MASK | 0x14) #define STATUS_EFI_ABORTED (EFI_ERROR_MASK | 0x15) #define STATUS_EFI_ICMP_ERROR (EFI_ERROR_MASK | 0x16) #define STATUS_EFI_TFTP_ERROR (EFI_ERROR_MASK | 0x17) #define STATUS_EFI_PROTOCOL_ERROR (EFI_ERROR_MASK | 0x18) #define STATUS_EFI_INCOMPATIBLE_VERSION (EFI_ERROR_MASK | 0x19) #define STATUS_EFI_SECURITY_VIOLATION (EFI_ERROR_MASK | 0x1A) #define STATUS_EFI_CRC_ERROR (EFI_ERROR_MASK | 0x1B) #define STATUS_EFI_END_OF_MEDIA (EFI_ERROR_MASK | 0x1C) #define STATUS_EFI_END_OF_FILE (EFI_ERROR_MASK | 0x1F) #define STATUS_EFI_INVALID_LANGUAGE (EFI_ERROR_MASK | 0x20) #define STATUS_EFI_COMPROMISED_DATA (EFI_ERROR_MASK | 0x21) #define STATUS_EFI_IP_ADDRESS_CONFLICT (EFI_ERROR_MASK | 0x22) #define STATUS_EFI_HTTP_ERROR (EFI_ERROR_MASK | 0x23) /* XT status code definitions */ #define STATUS_SUCCESS ((XTSTATUS) 0x00000000L) #define STATUS_END_OF_MEDIA ((XTSTATUS) 0x8000001EL) #define STATUS_RESOURCE_LOCKED ((XTSTATUS) 0xC0000000L) #define STATUS_UNSUCCESSFUL ((XTSTATUS) 0xC0000001L) #define STATUS_NOT_IMPLEMENTED ((XTSTATUS) 0xC0000002L) #define STATUS_ACCESS_VIOLATION ((XTSTATUS) 0xC0000005L) #define STATUS_IN_PAGE_ERROR ((XTSTATUS) 0xC0000006L) #define STATUS_INVALID_HANDLE ((XTSTATUS) 0xC0000008L) #define STATUS_BAD_INITIAL_STACK ((XTSTATUS) 0xC0000009L) #define STATUS_INVALID_PARAMETER ((XTSTATUS) 0xC000000DL) #define STATUS_END_OF_FILE ((XTSTATUS) 0xC0000011L) #define STATUS_NO_MEMORY ((XTSTATUS) 0xC0000017L) #define STATUS_PORT_DISCONNECTED ((XTSTATUS) 0xC0000037L) #define STATUS_CRC_ERROR ((XTSTATUS) 0xC000003FL) #define STATUS_FLOAT_OVERFLOW ((XTSTATUS) 0xC0000091L) #define STATUS_INTEGER_OVERFLOW ((XTSTATUS) 0xC0000095L) #define STATUS_INSUFFICIENT_RESOURCES ((XTSTATUS) 0xC000009AL) #define STATUS_DEVICE_NOT_READY ((XTSTATUS) 0xC00000A3L) #define STATUS_NOT_SUPPORTED ((XTSTATUS) 0xC00000BBL) #define STATUS_TIMEOUT ((XTSTATUS) 0x00000102L) #define STATUS_IO_DEVICE_ERROR ((XTSTATUS) 0xC0000185L) #define STATUS_NOT_FOUND ((XTSTATUS) 0xC0000225L) #endif /* __XTDK_XTSTATUS_H */ ================================================ FILE: sdk/xtdk/xtstruct.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtstruct.h * DESCRIPTION: XT structures forward references * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_XTSTRUCT_H #define __XTDK_XTSTRUCT_H #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Enumeration lists forward references */ typedef enum _ADJUST_REASON ADJUST_REASON, *PADJUST_REASON; typedef enum _EXCEPTION_DISPOSITION EXCEPTION_DISPOSITION, *PEXCEPTION_DISPOSITION; typedef enum _EFI_ALLOCATE_TYPE EFI_ALLOCATE_TYPE, *PEFI_ALLOCATE_TYPE; typedef enum _EFI_FRAMEWORK_CPU_DESIGNATION EFI_FRAMEWORK_CPU_DESIGNATION, *PEFI_FRAMEWORK_CPU_DESIGNATION; typedef enum _EFI_GRAPHICS_OUTPUT_BLT_OPERATION EFI_GRAPHICS_OUTPUT_BLT_OPERATION, *PEFI_GRAPHICS_OUTPUT_BLT_OPERATION; typedef enum _EFI_GRAPHICS_PIXEL_FORMAT EFI_GRAPHICS_PIXEL_FORMAT, *PEFI_GRAPHICS_PIXEL_FORMAT; typedef enum _EFI_GRAPHICS_PROTOCOL EFI_GRAPHICS_PROTOCOL, *PEFI_GRAPHICS_PROTOCOL; typedef enum _EFI_INTERFACE_TYPE EFI_INTERFACE_TYPE, *PEFI_INTERFACE_TYPE; typedef enum _EFI_IO_OPERATION_TYPE EFI_IO_OPERATION_TYPE, *PEFI_IO_OPERATION_TYPE; typedef enum _EFI_IO_WIDTH EFI_IO_WIDTH, *PEFI_IO_WIDTH; typedef enum _EFI_LOCATE_SEARCH_TYPE EFI_LOCATE_SEARCH_TYPE, *PEFI_LOCATE_SEARCH_TYPE; typedef enum _EFI_MEMORY_TYPE EFI_MEMORY_TYPE, *PEFI_MEMORY_TYPE; typedef enum _EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION, *PEFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION; typedef enum _EFI_PCI_IO_PROTOCOL_OPERATION EFI_PCI_IO_PROTOCOL_OPERATION, *PEFI_PCI_IO_PROTOCOL_OPERATION; typedef enum _EFI_PCI_IO_PROTOCOL_WIDTH EFI_PCI_IO_PROTOCOL_WIDTH, *PEFI_PCI_IO_PROTOCOL_WIDTH; typedef enum _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION, *PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION; typedef enum _EFI_PXE_BASE_CODE_CALLBACK_STATUS EFI_PXE_BASE_CODE_CALLBACK_STATUS, *PEFI_PXE_BASE_CODE_CALLBACK_STATUS; typedef enum _EFI_PXE_BASE_CODE_FUNCTION EFI_PXE_BASE_CODE_FUNCTION, *PEFI_PXE_BASE_CODE_FUNCTION; typedef enum _EFI_PXE_BASE_CODE_TFTP_OPCODE EFI_PXE_BASE_CODE_TFTP_OPCODE, *PEFI_PXE_BASE_CODE_TFTP_OPCODE; typedef enum _EFI_RESET_TYPE EFI_RESET_TYPE, *PEFI_RESET_TYPE; typedef enum _EFI_SIMPLE_NETWORK_STATE EFI_SIMPLE_NETWORK_STATE, *PEFI_SIMPLE_NETWORK_STATE; typedef enum _EFI_TIMER_DELAY EFI_TIMER_DELAY, *PEFI_TIMER_DELAY; typedef enum _EFI_UART_PARITY_TYPE EFI_UART_PARITY_TYPE, *PEFI_UART_PARITY_TYPE; typedef enum _EFI_UART_STOP_BITS_TYPE EFI_UART_STOP_BITS_TYPE, *PEFI_UART_STOP_BITS_TYPE; typedef enum _EFI_UNIVERSA_GRAPHICS_BLT_OPERATION EFI_UNIVERSA_GRAPHICS_BLT_OPERATION, *PEFI_UNIVERSA_GRAPHICS_BLT_OPERATION; typedef enum _HAL_APIC_MODE HAL_APIC_MODE, *PHAL_APIC_MODE; typedef enum _KAPC_ENVIRONMENT KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT; typedef enum _KDPC_IMPORTANCE KDPC_IMPORTANCE, *PKDPC_IMPORTANCE; typedef enum _KEVENT_TYPE KEVENT_TYPE, *PKEVENT_TYPE; typedef enum _KOBJECTS KOBJECTS, *PKOBJECTS; typedef enum _KPROCESS_STATE KPROCESS_STATE, *PKPROCESS_STATE; typedef enum _KPROFILE_SOURCE KPROFILE_SOURCE, *PKPROFILE_SOURCE; typedef enum _KTHREAD_STATE KTHREAD_STATE, *PKTHREAD_STATE; typedef enum _KTIMER_TYPE KTIMER_TYPE, *PKTIMER_TYPE; typedef enum _KUBSAN_DATA_TYPE KUBSAN_DATA_TYPE, *PKUBSAN_DATA_TYPE; typedef enum _LOADER_MEMORY_TYPE LOADER_MEMORY_TYPE, *PLOADER_MEMORY_TYPE; typedef enum _MMPAGELISTS MMPAGELISTS, *PMMPAGELISTS; typedef enum _MMPFN_CACHE_ATTRIBUTE MMPFN_CACHE_ATTRIBUTE, *PMMPFN_CACHE_ATTRIBUTE; typedef enum _MMPOOL_TYPE MMPOOL_TYPE, *PMMPOOL_TYPE; typedef enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE, *PMMSYSTEM_PTE_POOL_TYPE; typedef enum _MODE MODE, *PMODE; typedef enum _RTL_VARIABLE_TYPE RTL_VARIABLE_TYPE, *PRTL_VARIABLE_TYPE; typedef enum _SYSTEM_FIRMWARE_TYPE SYSTEM_FIRMWARE_TYPE, *PSYSTEM_FIRMWARE_TYPE; typedef enum _SYSTEM_RESOURCE_TYPE SYSTEM_RESOURCE_TYPE, *PSYSTEM_RESOURCE_TYPE; typedef enum _WAIT_TYPE WAIT_TYPE, *PWAIT_TYPE; /* Structures forward references */ typedef struct _ACPI_CACHE_LIST ACPI_CACHE_LIST, *PACPI_CACHE_LIST; typedef struct _ACPI_DESCRIPTION_HEADER ACPI_DESCRIPTION_HEADER, *PACPI_DESCRIPTION_HEADER; typedef struct _ACPI_FADT ACPI_FADT, *PACPI_FADT; typedef struct _ACPI_HPET ACPI_HPET, *PACPI_HPET; typedef struct _ACPI_MADT ACPI_MADT, *PACPI_MADT; typedef struct _ACPI_MADT_INTERRUPT_OVERRIDE ACPI_MADT_INTERRUPT_OVERRIDE, *PACPI_MADT_INTERRUPT_OVERRIDE; typedef struct _ACPI_MADT_IOAPIC ACPI_MADT_IOAPIC, *PACPI_MADT_IOAPIC; typedef struct _ACPI_MADT_LOCAL_APIC ACPI_MADT_LOCAL_APIC, *PACPI_MADT_LOCAL_APIC; typedef struct _ACPI_MADT_LOCAL_X2APIC ACPI_MADT_LOCAL_X2APIC, *PACPI_MADT_LOCAL_X2APIC; typedef struct _ACPI_RSDP ACPI_RSDP, *PACPI_RSDP; typedef struct _ACPI_RSDT ACPI_RSDT, *PACPI_RSDT; typedef struct _ACPI_SUBTABLE_HEADER ACPI_SUBTABLE_HEADER, *PACPI_SUBTABLE_HEADER; typedef struct _ACPI_SYSTEM_INFO ACPI_SYSTEM_INFO, *PACPI_SYSTEM_INFO; typedef struct _ACPI_TIMER_INFO ACPI_TIMER_INFO, *PACPI_TIMER_INFO; typedef struct _ACPI_XSDT ACPI_XSDT, *PACPI_XSDT; typedef struct _ANSI_STRING ANSI_STRING, *PANSI_STRING; typedef struct _ANSI_STRING32 ANSI_STRING32, *PANSI_STRING32; typedef struct _ANSI_STRING64 ANSI_STRING64, *PANSI_STRING64; typedef struct _CPPORT CPPORT, *PCPPORT; typedef const struct _CMMPAGEMAP_ROUTINES CMMPAGEMAP_ROUTINES, *PCMMPAGEMAP_ROUTINES; typedef struct _CSTRING CSTRING, *PCSTRING; typedef struct _EFI_1394_DEVICE_PATH EFI_1394_DEVICE_PATH, *PEFI_1394_DEVICE_PATH; typedef struct _EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR, *PEFI_ACPI_ADDRESS_SPACE_DESCRIPTOR; typedef struct _EFI_ACPI_ADR_DEVICE_PATH EFI_ACPI_ADR_DEVICE_PATH, *PEFI_ACPI_ADR_DEVICE_PATH; typedef struct _EFI_ACPI_HID_DEVICE_PATH EFI_ACPI_HID_DEVICE_PATH, *PEFI_ACPI_HID_DEVICE_PATH; typedef struct _EFI_ATAPI_DEVICE_PATH EFI_ATAPI_DEVICE_PATH, *PEFI_ATAPI_DEVICE_PATH; typedef struct _EFI_ATAPI_IDENTIFY EFI_ATAPI_IDENTIFY, *PEFI_ATAPI_IDENTIFY; typedef struct _EFI_BBS_BBS_DEVICE_PATH EFI_BBS_BBS_DEVICE_PATH, *PEFI_BBS_BBS_DEVICE_PATH; typedef struct _EFI_BBS_STATUS_FLAGS EFI_BBS_STATUS_FLAGS, *PEFI_BBS_STATUS_FLAGS; typedef struct _EFI_BBS_TABLE EFI_BBS_TABLE, *PEFI_BBS_TABLE; typedef struct _EFI_BLOCK_DEVICE EFI_BLOCK_DEVICE, *PEFI_BLOCK_DEVICE; typedef struct _EFI_BLOCK_DEVICE_DATA EFI_BLOCK_DEVICE_DATA, *PEFI_BLOCK_DEVICE_DATA; typedef struct _EFI_BLOCK_IO_MEDIA EFI_BLOCK_IO_MEDIA, *PEFI_BLOCK_IO_MEDIA; typedef struct _EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL, *PEFI_BLOCK_IO_PROTOCOL; typedef struct _EFI_BLOCK_IO2_PROTOCOL EFI_BLOCK_IO2_PROTOCOL, *PEFI_BLOCK_IO2_PROTOCOL; typedef struct _EFI_BLOCK_IO2_TOKEN EFI_BLOCK_IO2_TOKEN, *PEFI_BLOCK_IO2_TOKEN; typedef struct _EFI_BOOT_SERVICES EFI_BOOT_SERVICES, *PEFI_BOOT_SERVICES; typedef struct _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL, *PEFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL; typedef struct _EFI_BYTE_REGS EFI_BYTE_REGS, *PEFI_BYTE_REGS; typedef struct _EFI_CAPSULE_BLOCK_DESCRIPTOR EFI_CAPSULE_BLOCK_DESCRIPTOR, *PEFI_CAPSULE_BLOCK_DESCRIPTOR; typedef struct _EFI_CAPSULE_HEADER EFI_CAPSULE_HEADER, *PEFI_CAPSULE_HEADER; typedef struct _EFI_CDROM_DEVICE_PATH EFI_CDROM_DEVICE_PATH, *PEFI_CDROM_DEVICE_PATH; typedef struct _EFI_COMPONENT_NAME_PROTOCOL EFI_COMPONENT_NAME_PROTOCOL, *PEFI_COMPONENT_NAME_PROTOCOL; typedef struct _EFI_COMPONENT_NAME2_PROTOCOL EFI_COMPONENT_NAME2_PROTOCOL, *PEFI_COMPONENT_NAME2_PROTOCOL; typedef struct _EFI_CONFIGURATION_TABLE EFI_CONFIGURATION_TABLE, *PEFI_CONFIGURATION_TABLE; typedef struct _EFI_CONTROLLER_DEVICE_PATH EFI_CONTROLLER_DEVICE_PATH, *PEFI_CONTROLLER_DEVICE_PATH; typedef struct _EFI_DEVICE_IO_PROTOCOL EFI_DEVICE_IO_PROTOCOL, *PEFI_DEVICE_IO_PROTOCOL; typedef struct _EFI_DEVICE_LOGICAL_UNIT_DEVICE_PATH EFI_DEVICE_LOGICAL_UNIT_DEVICE_PATH, *PEFI_DEVICE_LOGICAL_UNIT_DEVICE_PATH; typedef struct _EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL, *PEFI_DEVICE_PATH_FROM_TEXT_PROTOCOL; typedef struct _EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL, *PEFI_DEVICE_PATH_PROTOCOL; typedef struct _EFI_DEVICE_PATH_TO_TEXT_PROTOCOL EFI_DEVICE_PATH_TO_TEXT_PROTOCOL, *PEFI_DEVICE_PATH_TO_TEXT_PROTOCOL; typedef struct _EFI_DEVICE_PATH_UTILITIES_PROTOCOL EFI_DEVICE_PATH_UTILITIES_PROTOCOL, *PEFI_DEVICE_PATH_UTILITIES_PROTOCOL; typedef struct _EFI_DISK_IO_PROTOCOL EFI_DISK_IO_PROTOCOL, *PEFI_DISK_IO_PROTOCOL; typedef struct _EFI_DISK_IO2_PROTOCOL EFI_DISK_IO2_PROTOCOL, *PEFI_DISK_IO2_PROTOCOL; typedef struct _EFI_DISK_IO2_TOKEN EFI_DISK_IO2_TOKEN, *PEFI_DISK_IO2_TOKEN; typedef struct _EFI_DRIVER_BINDING_PROTOCOL EFI_DRIVER_BINDING_PROTOCOL, *PEFI_DRIVER_BINDING_PROTOCOL; typedef struct _EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL, *PEFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL; typedef struct _EFI_DWORD_REGS EFI_DWORD_REGS, *PEFI_DWORD_REGS; typedef struct _EFI_EBC_PROTOCOL EFI_EBC_PROTOCOL, *PEFI_EBC_PROTOCOL; typedef struct _EFI_EDID_ACTIVE_PROTOCOL EFI_EDID_ACTIVE_PROTOCOL, *PEFI_EDID_ACTIVE_PROTOCOL; typedef struct _EFI_EDID_DISCOVERED_PROTOCOL EFI_EDID_DISCOVERED_PROTOCOL, *PEFI_EDID_DISCOVERED_PROTOCOL; typedef struct _EFI_EDID_OVERRIDE_PROTOCOL EFI_EDID_OVERRIDE_PROTOCOL, *PEFI_EDID_OVERRIDE_PROTOCOL; typedef struct _EFI_EFLAGS_REG EFLAGS_REG, *PEFI_EFLAGS_REG; typedef struct _EFI_EXPANDED_ACPI_HID_DEVICE_PATH EFI_EXPANDED_ACPI_HID_DEVICE_PATH, *PEFI_EXPANDED_ACPI_HID_DEVICE_PATH; typedef struct _EFI_FIBRECHANNEL_DEVICE_PATH EFI_FIBRECHANNEL_DEVICE_PATH, *PEFI_FIBRECHANNEL_DEVICE_PATH; typedef struct _EFI_FIBRECHANNELEX_DEVICE_PATH EFI_FIBRECHANNELEX_DEVICE_PATH, *PEFI_FIBRECHANNELEX_DEVICE_PATH; typedef struct _EFI_FILE_HANDLE EFI_FILE_HANDLE, *PEFI_FILE_HANDLE; typedef struct _EFI_FILE_HEADER EFI_FILE_HEADER, *PEFI_FILE_HEADER; typedef struct _EFI_FILE_INFO EFI_FILE_INFO, *PEFI_FILE_INFO; typedef struct _EFI_FILE_IO_TOKEN EFI_FILE_IO_TOKEN, *PEFI_FILE_IO_TOKEN; typedef struct _EFI_FILE_SYSTEM_INFO EFI_FILE_SYSTEM_INFO, *PEFI_FILE_SYSTEM_INFO; typedef struct _EFI_FILE_SYSTEM_VOLUME_LABEL EFI_FILE_SYSTEM_VOLUME_LABEL, *PEFI_FILE_SYSTEM_VOLUME_LABEL; typedef struct _EFI_FILEPATH_DEVICE_PATH EFI_FILEPATH_DEVICE_PATH, *PEFI_FILEPATH_DEVICE_PATH; typedef struct _EFI_FLAGS_REG EFI_FLAGS_REG, *PEFI_FLAGS_REG; typedef struct _EFI_FRAMEWORK_MP_HEALTH EFI_FRAMEWORK_MP_HEALTH, *PEFI_FRAMEWORK_MP_HEALTH; typedef struct _EFI_FRAMEWORK_MP_PROCESSOR_CONTEXT EFI_FRAMEWORK_MP_PROCESSOR_CONTEXT, *PEFI_FRAMEWORK_MP_PROCESSOR_CONTEXT; typedef struct _EFI_FRAMEWORK_MP_SERVICES_PROTOCOL EFI_FRAMEWORK_MP_SERVICES_PROTOCOL, *PEFI_FRAMEWORK_MP_SERVICES_PROTOCOL; typedef struct _EFI_GPT_PARTITION_TABLE_HEADER EFI_GPT_PARTITION_TABLE_HEADER, *PEFI_GPT_PARTITION_TABLE_HEADER; typedef struct _EFI_GPT_PARTITION_ENTRY EFI_GPT_PARTITION_ENTRY, *PEFI_GPT_PARTITION_ENTRY; typedef struct _EFI_GRAPHICS_OUTPUT_BLT_PIXEL EFI_GRAPHICS_OUTPUT_BLT_PIXEL, *PEFI_GRAPHICS_OUTPUT_BLT_PIXEL; typedef struct _EFI_GRAPHICS_OUTPUT_MODE_INFORMATION EFI_GRAPHICS_OUTPUT_MODE_INFORMATION, *PEFI_GRAPHICS_OUTPUT_MODE_INFORMATION; typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL, *PEFI_GRAPHICS_OUTPUT_PROTOCOL; typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE, *PEFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; typedef struct _EFI_GUID EFI_GUID, *PEFI_GUID; typedef struct _EFI_HARDDRIVE_DEVICE_PATH EFI_HARDDRIVE_DEVICE_PATH, *PEFI_HARDDRIVE_DEVICE_PATH; typedef struct _EFI_HASH_PROTOCOL EFI_HASH_PROTOCOL, *PEFI_HASH_PROTOCOL; typedef struct _EFI_HDD_INFO EFI_HDD_INFO, *PEFI_HDD_INFO; typedef struct _EFI_I2O_DEVICE_PATH EFI_I2O_DEVICE_PATH, *PEFI_I2O_DEVICE_PATH; typedef struct _EFI_INFINIBAND_DEVICE_PATH EFI_INFINIBAND_DEVICE_PATH, *PEFI_INFINIBAND_DEVICE_PATH; typedef struct _EFI_INPUT_KEY EFI_INPUT_KEY, *PEFI_INPUT_KEY; typedef struct _EFI_IO_ACCESS EFI_IO_ACCESS, *PEFI_IO_ACCESS; typedef struct _EFI_IPv4_ADDRESS EFI_IPv4_ADDRESS, *PEFI_IPv4_ADDRESS; typedef struct _EFI_IPv4_DEVICE_PATH EFI_IPv4_DEVICE_PATH, *PEFI_IPv4_DEVICE_PATH; typedef struct _EFI_IPv6_ADDRESS EFI_IPv6_ADDRESS, *PEFI_IPv6_ADDRESS; typedef struct _EFI_IPv6_DEVICE_PATH EFI_IPv6_DEVICE_PATH, *PEFI_IPv6_DEVICE_PATH; typedef struct _EFI_KEY_DATA EFI_KEY_DATA, *PEFI_KEY_DATA; typedef struct _EFI_KEY_STATE EFI_KEY_STATE, *PEFI_KEY_STATE; typedef struct _EFI_LBAL EFI_LBAL, *PEFI_LBAL; typedef struct _EFI_LEGACY_BIOS_PROTOCOL EFI_LEGACY_BIOS_PROTOCOL, *PEFI_LEGACY_BIOS_PROTOCOL; typedef struct _EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE_PROTOCOL, *PEFI_LOAD_FILE_PROTOCOL; typedef struct _EFI_LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE_PROTOCOL, *PEFI_LOADED_IMAGE_PROTOCOL; typedef struct _EFI_MAC_ADDR_DEVICE_PATH EFI_MAC_ADDR_DEVICE_PATH, *PEFI_MAC_ADDR_DEVICE_PATH; typedef struct _EFI_MAC_ADDRESS EFI_MAC_ADDRESS, *PEFI_MAC_ADDRESS; typedef struct _EFI_MANAGED_NETWORK_CONFIG_DATA EFI_MANAGED_NETWORK_CONFIG_DATA, *PEFI_MANAGED_NETWORK_CONFIG_DATA; typedef struct _EFI_MASTER_BOOT_RECORD EFI_MASTER_BOOT_RECORD, *PEFI_MASTER_BOOT_RECORD; typedef struct _EFI_MBR_PARTITION_RECORD EFI_MBR_PARTITION_RECORD, *PEFI_MBR_PARTITION_RECORD; typedef struct _EFI_MEDIA_FW_VOL_DEVICE_PATH EFI_MEDIA_FW_VOL_DEVICE_PATH, *PEFI_MEDIA_FW_VOL_DEVICE_PATH; typedef struct _EFI_MEDIA_FW_VOL_FILEPATH_DEVICE_PATH EFI_MEDIA_FW_VOL_FILEPATH_DEVICE_PATH, *PEFI_MEDIA_FW_VOL_FILEPATH_DEVICE_PATH; typedef struct _EFI_MEDIA_PROTOCOL_DEVICE_PATH EFI_MEDIA_PROTOCOL_DEVICE_PATH, *PEFI_MEDIA_PROTOCOL_DEVICE_PATH; typedef struct _EFI_MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH EFI_MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH, *PEFI_MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH; typedef struct _EFI_MEMMAP_DEVICE_PATH EFI_MEMMAP_DEVICE_PATH, *PEFI_MEMMAP_DEVICE_PATH; typedef struct _EFI_MEMORY_DESCRIPTOR EFI_MEMORY_DESCRIPTOR, *PEFI_MEMORY_DESCRIPTOR; typedef struct _EFI_MEMORY_MAP EFI_MEMORY_MAP, *PEFI_MEMORY_MAP; typedef struct _EFI_MP_SERVICES_PROTOCOL EFI_MP_SERVICES_PROTOCOL, *PEFI_MP_SERVICES_PROTOCOL; typedef struct _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL, *PEFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE; typedef struct _EFI_NETWORK_STATISTICS EFI_NETWORK_STATISTICS, *PEFI_NETWORK_STATISTICS; typedef struct _EFI_OPEN_PROTOCOL_INFORMATION_ENTRY EFI_OPEN_PROTOCOL_INFORMATION_ENTRY, *PEFI_OPEN_PROTOCOL_INFORMATION_ENTRY; typedef struct _EFI_PARTITION_HEADER EFI_PARTITION_HEADER, *PEFI_PARTITION_HEADER; typedef struct _EFI_PCCARD_DEVICE_PATH EFI_PCCARD_DEVICE_PATH, *PEFI_PCCARD_DEVICE_PATH; typedef struct _EFI_PCI_DEVICE_PATH EFI_PCI_DEVICE_PATH, *PEFI_PCI_DEVICE_PATH; typedef struct _EFI_PCI_IO_PROTOCOL EFI_PCI_IO_PROTOCOL, *PEFI_PCI_IO_PROTOCOL; typedef struct _EFI_PCI_IO_PROTOCOL_ACCESS EFI_PCI_IO_PROTOCOL_ACCESS, *PEFI_PCI_IO_PROTOCOL_ACCESS; typedef struct _EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS, *PEFI_PCI_IO_PROTOCOL_CONFIG_ACCESS; typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL, *PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL; typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS, *PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS; typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS, *PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS; typedef struct _EFI_PIXEL_BITMASK EFI_PIXEL_BITMASK, *PEFI_PIXEL_BITMASK; typedef struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL, *PEFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL; typedef struct _EFI_PROCESSOR_INFORMATION EFI_PROCESSOR_INFORMATION, *PEFI_PROCESSOR_INFORMATION; typedef struct _EFI_PROCESSOR_PHYSICAL_LOCATION EFI_PROCESSOR_PHYSICAL_LOCATION, *PEFI_PROCESSOR_PHYSICAL_LOCATION; typedef struct _EFI_PXE_BASE_CODE_ARP_ENTRY EFI_PXE_BASE_CODE_ARP_ENTRY, *PEFI_PXE_BASE_CODE_ARP_ENTRY; typedef struct _EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL, *PEFI_PXE_BASE_CODE_CALLBACK_PROTOCOL; typedef struct _EFI_PXE_BASE_CODE_DHCPV4_PACKET EFI_PXE_BASE_CODE_DHCPV4_PACKET, *PEFI_PXE_BASE_CODE_DHCPV4_PACKET; typedef struct _EFI_PXE_BASE_CODE_DHCPV6_PACKET EFI_PXE_BASE_CODE_DHCPV6_PACKET, *PEFI_PXE_BASE_CODE_DHCPV6_PACKET; typedef struct _EFI_PXE_BASE_CODE_DISCOVER_INFO EFI_PXE_BASE_CODE_DISCOVER_INFO, *PEFI_PXE_BASE_CODE_DISCOVER_INFO; typedef struct _EFI_PXE_BASE_CODE_ICMP_ERROR EFI_PXE_BASE_CODE_ICMP_ERROR, *PEFI_PXE_BASE_CODE_ICMP_ERROR; typedef struct _EFI_PXE_BASE_CODE_IP_FILTER EFI_PXE_BASE_CODE_IP_FILTER, *PEFI_PXE_BASE_CODE_IP_FILTER; typedef struct _EFI_PXE_BASE_CODE_MODE EFI_PXE_BASE_CODE_MODE, *PEFI_PXE_BASE_CODE_MODE; typedef struct _EFI_PXE_BASE_CODE_MTFTP_INFO EFI_PXE_BASE_CODE_MTFTP_INFO, *PEFI_PXE_BASE_CODE_MTFTP_INFO; typedef struct _EFI_PXE_BASE_CODE_PROTOCOL EFI_PXE_BASE_CODE_PROTOCOL, *PEFI_PXE_BASE_CODE_PROTOCOL; typedef struct _EFI_PXE_BASE_CODE_ROUTE_ENTRY EFI_PXE_BASE_CODE_ROUTE_ENTRY, *PEFI_PXE_BASE_CODE_ROUTE_ENTRY; typedef struct _EFI_PXE_BASE_CODE_SRVLIST EFI_PXE_BASE_CODE_SRVLIST, *PEFI_PXE_BASE_CODE_SRVLIST; typedef struct _EFI_PXE_BASE_CODE_TFTP_ERROR EFI_PXE_BASE_CODE_TFTP_ERROR, *PEFI_PXE_BASE_CODE_TFTP_ERROR; typedef struct _EFI_RL EFI_RL, *PEFI_RL; typedef struct _EFI_RNG_PROTOCOL EFI_RNG_PROTOCOL, *PEFI_RNG_PROTOCOL; typedef struct _EFI_RUNTIME_SERVICES EFI_RUNTIME_SERVICES, *PEFI_RUNTIME_SERVICES; typedef struct _EFI_SATA_DEVICE_PATH EFI_SATA_DEVICE_PATH, *PEFI_SATA_DEVICE_PATH; typedef struct _EFI_SCSI_DEVICE_PATH EFI_SCSI_DEVICE_PATH, *PEFI_SCSI_DEVICE_PATH; typedef struct _EFI_SERVICE_BINDING EFI_SERVICE_BINDING, *PEFI_SERVICE_BINDING; typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, *PEFI_SIMPLE_FILE_SYSTEM_PROTOCOL; typedef struct _EFI_SIMPLE_NETWORK_MODE EFI_SIMPLE_NETWORK_MODE, *PEFI_SIMPLE_NETWORK_MODE; typedef struct _EFI_SIMPLE_NETWORK_PROTOCOL EFI_SIMPLE_NETWORK_PROTOCOL, *PEFI_SIMPLE_NETWORK_PROTOCOL; typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL, *PEFI_SIMPLE_TEXT_INPUT_PROTOCOL; typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL, *PEFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL; typedef struct _EFI_SIMPLE_TEXT_OUTPUT_MODE EFI_SIMPLE_TEXT_OUTPUT_MODE, *PEFI_SIMPLE_TEXT_OUTPUT_MODE; typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL, *PEFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; typedef struct _EFI_SYSTEM_TABLE EFI_SYSTEM_TABLE, *PEFI_SYSTEM_TABLE; typedef struct _EFI_TABLE_HEADER EFI_TABLE_HEADER, *PEFI_TABLE_HEADER; typedef struct _EFI_TIME EFI_TIME, *PEFI_TIME; typedef struct _EFI_TIME_CAPABILITIES EFI_TIME_CAPABILITIES, *PEFI_TIME_CAPABILITIES; typedef struct _EFI_UART_DEVICE_PATH EFI_UART_DEVICE_PATH, *PEFI_UART_DEVICE_PATH; typedef struct _EFI_UART_IO_MODE EFI_UART_IO_MODE, *PEFI_UART_IO_MODE; typedef struct _EFI_UART_IO_PROTOCOL EFI_UART_IO_PROTOCOL, *PEFI_UART_IO_PROTOCOL; typedef struct _EFI_UDC_ATTRIBUTES EFI_UDC_ATTRIBUTES, *PEFI_UDC_ATTRIBUTES; typedef struct _EFI_UKNOWN_DEVICE_VENDOR_DEVICE_PATH EFI_UNKNOWN_DEVICE_VENDOR_DEVICE_PATH, *PEFI_UNKNOWN_DEVICE_VENDOR_DEVICE_PATH; typedef struct _EFI_UNICODE_COLLATION_PROTOCOL EFI_UNICODE_COLLATION_PROTOCOL, *PEFI_UNICODE_COLLATION_PROTOCOL; typedef struct _EFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL EFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL, *PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL; typedef struct _EFI_UNIVERSAL_GRAPHICS_BLT_PIXEL EFI_UNIVERSAL_GRAPHICS_BLT_PIXEL, *PEFI_UNIVERSAL_GRAPHICS_BLT_PIXEL; typedef struct _EFI_URI_DEVICE_PATH EFI_URI_DEVICE_PATH, *PEFI_URI_DEVICE_PATH; typedef struct _EFI_USB_CLASS_DEVICE_PATH EFI_USB_CLASS_DEVICE_PATH, *PEFI_USB_CLASS_DEVICE_PATH; typedef struct _EFI_USB_DEVICE_PATH EFI_USB_DEVICE_PATH, *PEFI_USB_DEVICE_PATH; typedef struct _EFI_USB_WWID_DEVICE_PATH EFI_USB_WWID_DEVICE_PATH, *PEFI_USB_WWID_DEVICE_PATH; typedef struct _EFI_VENDOR_DEVICE_PATH EFI_VENDOR_DEVICE_PATH, *PEFI_VENDOR_DEVICE_PATH; typedef struct _EFI_VLAN_DEVICE_PATH EFI_VLAN_DEVICE_PATH, *PEFI_VLAN_DEVICE_PATH; typedef struct _EFI_WORD_REGS EFI_WORD_REGS, *PEFI_WORD_REGS; typedef struct _EPROCESS EPROCESS, *PEPROCESS; typedef struct _ETHREAD ETHREAD, *PETHREAD; typedef struct _EX_RUNDOWN_REFERENCE EX_RUNDOWN_REFERENCE, *PEX_RUNDOWN_REFERENCE; typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD, *PEXCEPTION_RECORD; typedef struct _EXCEPTION_REGISTRATION_RECORD EXCEPTION_REGISTRATION_RECORD, *PEXCEPTION_REGISTRATION_RECORD; typedef struct _FIRMWARE_INFORMATION_BLOCK FIRMWARE_INFORMATION_BLOCK, *PFIRMWARE_INFORMATION_BLOCK; typedef struct _FLOAT128 FLOAT128, *PFLOAT128; typedef struct _GENERIC_ADDRESS GENERIC_ADDRESS, *PGENERIC_ADDRESS; typedef struct _GUID GUID, *PGUID; typedef struct _HL_FRAMEBUFFER_DATA HL_FRAMEBUFFER_DATA, *PHL_FRAMEBUFFER_DATA; typedef struct _HL_SCROLL_REGION_DATA HL_SCROLL_REGION_DATA, *PHL_SCROLL_REGION_DATA; typedef struct _KAPC KAPC, *PKAPC; typedef struct _KAPC_STATE KAPC_STATE, *PKAPC_STATE; typedef struct _KD_DEBUG_MODE KD_DEBUG_MODE, *PKD_DEBUG_MODE; typedef struct _KD_DISPATCH_TABLE KD_DISPATCH_TABLE, *PKD_DISPATCH_TABLE; typedef struct _KDPC KDPC, *PKDPC; typedef struct _KDPC_DATA KDPC_DATA, *PKDPC_DATA; typedef struct _KERNEL_INITIALIZATION_BLOCK KERNEL_INITIALIZATION_BLOCK, *PKERNEL_INITIALIZATION_BLOCK; typedef struct _KEVENT KEVENT, *PKEVENT; typedef struct _KGATE KGATE, *PKGATE; typedef struct _KLOCK_QUEUE_HANDLE KLOCK_QUEUE_HANDLE, *PKLOCK_QUEUE_HANDLE; typedef struct _KPROCESS KPROCESS, *PKPROCESS; typedef struct _KQUEUE KQUEUE, *PKQUEUE; typedef struct _KSEMAPHORE KSEMAPHORE, *PKSEMAPHORE; typedef struct _KSERVICE_DESCRIPTOR_TABLE KSERVICE_DESCRIPTOR_TABLE, *PKSERVICE_DESCRIPTOR_TABLE; typedef struct _KSHARED_DATA KSHARED_DATA, *PKSHARED_DATA; typedef struct _KSPIN_LOCK_QUEUE KSPIN_LOCK_QUEUE, *PKSPIN_LOCK_QUEUE; typedef struct _KSYSTEM_TIME KSYSTEM_TIME, *PKSYSTEM_TIME; typedef struct _KTHREAD KTHREAD, *PKTHREAD; typedef struct _KTIMER KTIMER, *PKTIMER; typedef struct _KUBSAN_FLOAT_CAST_OVERFLOW_DATA KUBSAN_FLOAT_CAST_OVERFLOW_DATA, *PKUBSAN_FLOAT_CAST_OVERFLOW_DATA; typedef struct _KUBSAN_FUNCTION_TYPE_MISMATCH_DATA KUBSAN_FUNCTION_TYPE_MISMATCH_DATA, *PKUBSAN_FUNCTION_TYPE_MISMATCH_DATA; typedef struct _KUBSAN_INVALID_BUILTIN_DATA KUBSAN_INVALID_BUILTIN_DATA, *PKUBSAN_INVALID_BUILTIN_DATA; typedef struct _KUBSAN_OUT_OF_BOUNDS_DATA KUBSAN_OUT_OF_BOUNDS_DATA, *PKUBSAN_OUT_OF_BOUNDS_DATA; typedef struct _KUBSAN_OVERFLOW_DATA KUBSAN_OVERFLOW_DATA, *PKUBSAN_OVERFLOW_DATA; typedef struct _KUBSAN_SHIFT_OUT_OF_BOUNDS_DATA KUBSAN_SHIFT_OUT_OF_BOUNDS_DATA, *PKUBSAN_SHIFT_OUT_OF_BOUNDS_DATA; typedef struct _KUBSAN_SOURCE_LOCATION KUBSAN_SOURCE_LOCATION, *PKUBSAN_SOURCE_LOCATION; typedef struct _KUBSAN_TYPE_DESCRIPTOR KUBSAN_TYPE_DESCRIPTOR, *PKUBSAN_TYPE_DESCRIPTOR; typedef struct _KUBSAN_TYPE_MISMATCH_DATA KUBSAN_TYPE_MISMATCH_DATA, *PKUBSAN_TYPE_MISMATCH_DATA; typedef struct _KUBSAN_TYPE_MISMATCH_DATA_V1 KUBSAN_TYPE_MISMATCH_DATA_V1, *PKUBSAN_TYPE_MISMATCH_DATA_V1; typedef struct _KWAIT_BLOCK KWAIT_BLOCK, *PKWAIT_BLOCK; typedef struct _LDR_DATA_TABLE_ENTRY LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; typedef struct _LIST_ENTRY LIST_ENTRY, *PLIST_ENTRY; typedef struct _LIST_ENTRY32 LIST_ENTRY32, *PLIST_ENTRY32; typedef struct _LIST_ENTRY64 LIST_ENTRY64, *PLIST_ENTRY64; typedef struct _LOADER_GRAPHICS_INFORMATION_BLOCK LOADER_GRAPHICS_INFORMATION_BLOCK, *PLOADER_GRAPHICS_INFORMATION_BLOCK; typedef struct _LOADER_INFORMATION_BLOCK LOADER_INFORMATION_BLOCK, *PLOADER_INFORMATION_BLOCK; typedef struct _LOADER_MEMORY_DESCRIPTOR LOADER_MEMORY_DESCRIPTOR, *PLOADER_MEMORY_DESCRIPTOR; typedef struct _M128 M128, *PM128; typedef struct _MMCOLOR_TABLES MMCOLOR_TABLES, *PMMCOLOR_TABLES; typedef struct _MMFREE_POOL_ENTRY MMFREE_POOL_ENTRY, *PMMFREE_POOL_ENTRY; typedef struct _MMMEMORY_LAYOUT MMMEMORY_LAYOUT, *PMMMEMORY_LAYOUT; typedef struct _MMPFNENTRY MMPFNENTRY, *PMMPFNENTRY; typedef struct _MMPFNLIST MMPFNLIST, *PMMPFNLIST; typedef struct _PCAT_FIRMWARE_INFORMATION PCAT_FIRMWARE_INFORMATION, *PPCAT_FIRMWARE_INFORMATION; typedef struct _PCI_BRIDGE_CONTROL_REGISTER PCI_BRIDGE_CONTROL_REGISTER, *PPCI_BRIDGE_CONTROL_REGISTER; typedef struct _PCI_COMMON_CONFIG PCI_COMMON_CONFIG, *PPCI_COMMON_CONFIG; typedef struct _PCI_COMMON_HEADER PCI_COMMON_HEADER, *PPCI_COMMON_HEADER; typedef struct _PCI_DEVICE_HEADER_TYPE_REGION PCI_DEVICE_HEADER_TYPE_REGION, *PPCI_DEVICE_HEADER_TYPE_REGION; typedef struct _PCI_DEVICE_INDEPENDENT_REGION PCI_DEVICE_INDEPENDENT_REGION, *PPCI_DEVICE_INDEPENDENT_REGION; typedef struct _PCI_TYPE0_DEVICE PCI_TYPE0_DEVICE, *PPCI_TYPE0_DEVICE; typedef struct _PCI_TYPE1_DEVICE PCI_TYPE1_DEVICE, *PPCI_TYPE1_DEVICE; typedef struct _PECOFF_IMAGE_BASE_RELOCATION PECOFF_IMAGE_BASE_RELOCATION, *PPECOFF_IMAGE_BASE_RELOCATION; typedef struct _PECOFF_IMAGE_DATA PECOFF_IMAGE_DATA, *PPECOFF_IMAGE_DATA; typedef struct _PECOFF_IMAGE_DATA_DIRECTORY PECOFF_IMAGE_DATA_DIRECTORY, *PPECOFF_IMAGE_DATA_DIRECTORY; typedef struct _PECOFF_IMAGE_DOS_HEADER PECOFF_IMAGE_DOS_HEADER, *PPECOFF_IMAGE_DOS_HEADER; typedef struct _PECOFF_IMAGE_EXPORT_DIRECTORY PECOFF_IMAGE_EXPORT_DIRECTORY, *PPECOFF_IMAGE_EXPORT_DIRECTORY; typedef struct _PECOFF_IMAGE_FILE_HEADER PECOFF_IMAGE_FILE_HEADER, *PPECOFF_IMAGE_FILE_HEADER; typedef struct _PECOFF_IMAGE_IMPORT_DESCRIPTOR PECOFF_IMAGE_IMPORT_DESCRIPTOR, *PPECOFF_IMAGE_IMPORT_DESCRIPTOR; typedef struct _PECOFF_IMAGE_LOAD_CONFIG_CODE_INTEGRITY PECOFF_IMAGE_LOAD_CONFIG_CODE_INTEGRITY, *PPECOFF_IMAGE_LOAD_CONFIG_CODE_INTEGRITY; typedef struct _PECOFF_IMAGE_LOAD_CONFIG_DIRECTORY32 PECOFF_IMAGE_LOAD_CONFIG_DIRECTORY32, *PPECOFF_IMAGE_LOAD_CONFIG_DIRECTORY32; typedef struct _PECOFF_IMAGE_LOAD_CONFIG_DIRECTORY64 PECOFF_IMAGE_LOAD_CONFIG_DIRECTORY64, *PPECOFF_IMAGE_LOAD_CONFIG_DIRECTORY64; typedef struct _PECOFF_IMAGE_OPTIONAL_HEADER PECOFF_IMAGE_OPTIONAL_HEADER, *PPECOFF_IMAGE_OPTIONAL_HEADER; typedef struct _PECOFF_IMAGE_OS2_HEADER PECOFF_IMAGE_OS2_HEADER, *PPECOFF_IMAGE_OS2_HEADER; typedef struct _PECOFF_IMAGE_PE_HEADER PECOFF_IMAGE_PE_HEADER, *PPECOFF_IMAGE_PE_HEADER; typedef struct _PECOFF_IMAGE_RESOURCE_DATA_ENTRY PECOFF_IMAGE_RESOURCE_DATA_ENTRY, *PPECOFF_IMAGE_RESOURCE_DATA_ENTRY; typedef struct _PECOFF_IMAGE_RESOURCE_DIRECTORY PECOFF_IMAGE_RESOURCE_DIRECTORY, *PPECOFF_IMAGE_RESOURCE_DIRECTORY; typedef struct _PECOFF_IMAGE_RESOURCE_DIRECTORY_ENTRY PECOFF_IMAGE_RESOURCE_DIRECTORY_ENTRY, *PPECOFF_IMAGE_RESOURCE_DIRECTORY_ENTRY; typedef struct _PECOFF_IMAGE_ROM_HEADER PECOFF_IMAGE_ROM_HEADER, *PPECOFF_IMAGE_ROM_HEADER; typedef struct _PECOFF_IMAGE_ROM_OPTIONAL_HEADER PECOFF_IMAGE_ROM_OPTIONAL_HEADER, *PPECOFF_IMAGE_ROM_OPTIONAL_HEADER; typedef struct _PECOFF_IMAGE_SECTION_HEADER PECOFF_IMAGE_SECTION_HEADER, *PPECOFF_IMAGE_SECTION_HEADER; typedef struct _PECOFF_IMAGE_VXD_HEADER PECOFF_IMAGE_VXD_HEADER, *PPECOFF_IMAGE_VXD_HEADER; typedef struct _PHYSICAL_MEMORY_DESCRIPTOR PHYSICAL_MEMORY_DESCRIPTOR, *PPHYSICAL_MEMORY_DESCRIPTOR; typedef struct _PHYSICAL_MEMORY_RUN PHYSICAL_MEMORY_RUN, *PPHYSICAL_MEMORY_RUN; typedef struct _POOL_HEADER POOL_HEADER, *PPOOL_HEADER; typedef struct _POOL_TRACKING_BIG_ALLOCATIONS POOL_TRACKING_BIG_ALLOCATIONS, *PPOOL_TRACKING_BIG_ALLOCATIONS; typedef struct _POOL_TRACKING_TABLE POOL_TRACKING_TABLE, *PPOOL_TRACKING_TABLE; typedef struct _PROCESSOR_IDENTITY PROCESSOR_IDENTITY, *PPROCESSOR_IDENTITY; typedef struct _PROCESSOR_POWER_STATE PROCESSOR_POWER_STATE, *PPROCESSOR_POWER_STATE; typedef struct _RTL_BITMAP RTL_BITMAP, *PRTL_BITMAP; typedef struct _RTL_PRINT_CONTEXT RTL_PRINT_CONTEXT, *PRTL_PRINT_CONTEXT; typedef struct _RTL_PRINT_FORMAT_PROPERTIES RTL_PRINT_FORMAT_PROPERTIES, *PRTL_PRINT_FORMAT_PROPERTIES; typedef struct _SINGLE_LIST_ENTRY SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY; typedef struct _SMBIOS_TABLE_HEADER SMBIOS_TABLE_HEADER, *PSMBIOS_TABLE_HEADER; typedef struct _SMBIOS3_TABLE_HEADER SMBIOS3_TABLE_HEADER, *PSMBIOS3_TABLE_HEADER; typedef struct _STRING STRING, *PSTRING; typedef struct _STRING32 STRING32, *PSTRING32; typedef struct _STRING64 STRING64, *PSTRING64; typedef struct _THREAD_INFORMATION_BLOCK THREAD_INFORMATION_BLOCK, *PTHREAD_INFORMATION_BLOCK; typedef struct _TIME_FIELDS TIME_FIELDS, *PTIME_FIELDS; typedef struct _TIMER_ROUTINES TIMER_ROUTINES, *PTIMER_ROUTINES; typedef struct _UEFI_FIRMWARE_INFORMATION UEFI_FIRMWARE_INFORMATION, *PUEFI_FIRMWARE_INFORMATION; typedef struct _UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING; typedef struct _UNICODE_STRING32 UNICODE_STRING32, *PUNICODE_STRING32; typedef struct _UNICODE_STRING64 UNICODE_STRING64, *PUNICODE_STRING64; typedef struct _XTBL_BOOT_PARAMETERS XTBL_BOOT_PARAMETERS, *PXTBL_BOOT_PARAMETERS; typedef struct _XTBL_BOOT_PROTOCOL XTBL_BOOT_PROTOCOL, *PXTBL_BOOT_PROTOCOL; typedef struct _XTBL_BOOTMENU_ITEM XTBL_BOOTMENU_ITEM, *PXTBL_BOOTMENU_ITEM; typedef struct _XTBL_CONFIG_ENTRY XTBL_CONFIG_ENTRY, *PXTBL_CONFIG_ENTRY; typedef struct _XTBL_CONFIG_SECTION XTBL_CONFIG_SECTION, *PXTBL_CONFIG_SECTION; typedef struct _XTBL_DIALOG_HANDLE XTBL_DIALOG_HANDLE, *PXTBL_DIALOG_HANDLE; typedef struct _XTBL_EXECUTABLE_IMAGE_PROTOCOL XTBL_EXECUTABLE_IMAGE_PROTOCOL, *PXTBL_EXECUTABLE_IMAGE_PROTOCOL; typedef struct _XTBL_FRAMEBUFFER_INFORMATION XTBL_FRAMEBUFFER_INFORMATION, *PXTBL_FRAMEBUFFER_INFORMATION; typedef struct _XTBL_FRAMEBUFFER_MODE_INFORMATION XTBL_FRAMEBUFFER_MODE_INFORMATION, *PXTBL_FRAMEBUFFER_MODE_INFORMATION; typedef struct _XTBL_FRAMEBUFFER_PROTOCOL XTBL_FRAMEBUFFER_PROTOCOL, *PXTBL_FRAMEBUFFER_PROTOCOL; typedef struct _XTBL_KNOWN_BOOT_PROTOCOL XTBL_KNOWN_BOOT_PROTOCOL, *PXTBL_KNOWN_BOOT_PROTOCOL; typedef struct _XTBL_LOADER_PROTOCOL XTBL_LOADER_PROTOCOL, *PXTBL_LOADER_PROTOCOL; typedef struct _XTBL_MEMORY_MAPPING XTBL_MEMORY_MAPPING, *PXTBL_MEMORY_MAPPING; typedef struct _XTBL_MODULE_AUTHORS XTBL_MODULE_AUTHORS, *PXTBL_MODULE_AUTHORS; typedef struct _XTBL_MODULE_DEPS XTBL_MODULE_DEPS, *PXTBL_MODULE_DEPS; typedef struct _XTBL_MODULE_INFO XTBL_MODULE_INFO, *PXTBL_MODULE_INFO; typedef struct _XTBL_PAGE_MAPPING XTBL_PAGE_MAPPING, *PXTBL_PAGE_MAPPING; typedef struct _XTBL_STATUS XTBL_STATUS, *PXTBL_STATUS; /* Unions forward references */ typedef union _EFI_DEV_PATH EFI_DEV_PATH, *PEFI_DEV_PATH; typedef union _EFI_DEV_PATH_PTR EFI_DEV_PATH_PTR, *PEFI_DEV_PATH_PTR; typedef union _EFI_FRAMEWORK_MP_HEALTH_FLAGS EFI_FRAMEWORK_MP_HEALTH_FLAGS, *PEFI_FRAMEWORK_MP_HEALTH_FLAGS; typedef union _EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION, *PEFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION; typedef union _EFI_HASH_OUTPUT EFI_HASH_OUTPUT, *PEFI_HASH_OUTPUT; typedef union _EFI_IA32_REGISTER_SET EFI_IA32_REGISTER_SET, *PEFI_IA32_REGISTER_SET; typedef union _EFI_IP_ADDRESS EFI_IP_ADDRESS, *PEFI_IP_ADDRESS; typedef union _EFI_PXE_BASE_CODE_PACKET EFI_PXE_BASE_CODE_PACKET, *PEFI_PXE_BASE_CODE_PACKET; typedef union _LARGE_INTEGER LARGE_INTEGER, *PLARGE_INTEGER; typedef union _SINGLE_LIST_HEADER SINGLE_LIST_HEADER, *PSINGLE_LIST_HEADER; typedef union _ULARGE_INTEGER ULARGE_INTEGER, *PULARGE_INTEGER; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_XTSTRUCT_H */ ================================================ FILE: sdk/xtdk/xttarget.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xttarget.h * DESCRIPTION: XT target architecture specific definitions * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_XTTARGET_H #define __XTDK_XTTARGET_H /* Preprocessor macros for including arch-specific headers */ #define ARCH_COMMON(header) STRINGIFY(../_ARCH_COMMON/header) #define ARCH_HEADER(header) STRINGIFY(_ARCH/header) /* Architecture specific definitions */ #if defined(__i386__) || defined(__i686__) #define _ARCH i686 #define _ARCH_I686 1 #define _ARCH_COMMON x86 #define _ARCH_NAME "32-bit x86" #define _ARCH_IMAGE_MACHINE_TYPE 0x014C #define _XT32 1 #define BITS_PER_LONG 32 #define CACHE_ALIGNMENT 64 #define EFI_ERROR_MASK 0x80000000 #define MAXIMUM_PROCESSORS 32 #define MEMORY_ALIGNMENT 8 #define MM_USERPAGE_TABLES 1536 #define MM_VIRTUAL_PAGESIZE 20 #define STACK_ALIGNMENT 4 #elif defined(__amd64__) || defined(__x86_64__) #define _ARCH amd64 #define _ARCH_AMD64 1 #define _ARCH_COMMON x86 #define _ARCH_NAME "64-bit x86" #define _ARCH_IMAGE_MACHINE_TYPE 0x8664 #define _XT64 1 #define BITS_PER_LONG 64 #define CACHE_ALIGNMENT 64 #define EFI_ERROR_MASK 0x8000000000000000 #define MAXIMUM_PROCESSORS 256 #define MEMORY_ALIGNMENT 16 #define MM_USERPAGE_TABLES 4194304 #define MM_VIRTUAL_PAGESIZE 52 #define STACK_ALIGNMENT 16 #else #error Unknown architecture #endif #endif /* __XTDK_XTTARGET_H */ ================================================ FILE: sdk/xtdk/xttypes.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xttypes.h * DESCRIPTION: Definitions of basic data types defined by XT * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_XTTYPES_H #define __XTDK_XTTYPES_H #include #include /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Standard C types */ typedef unsigned char BYTE, *PBYTE, *LPBYTE; typedef char CHAR, *PCHAR, *LPCHAR; typedef double DOUBLE, *PDOUBLE, *LPDOUBLE; typedef unsigned long DWORD, *PDWORD, *LPDWORD; typedef float FLOAT, *PFLOAT, *LPFLOAT; typedef int INT, *PINT, *LPINT; typedef long LONG, *PLONG, *LPLONG; typedef signed char SCHAR, *PSCHAR; typedef signed long SLONG, *PSLONG; typedef short SHORT, *PSHORT, *LPSHORT; typedef unsigned char UCHAR, *PUCHAR; typedef unsigned int UINT, *PUINT; typedef unsigned long ULONG, *PULONG, LPULONG; typedef unsigned short USHORT, *PUSHORT; typedef unsigned short WORD, *PWORD, *LPWORD; typedef void VOID, *PVOID, *LPVOID; /* Constant C types */ typedef const BYTE CBYTE, *PCBYTE, *LPCBYTE; typedef const CHAR CCHAR, *PCCHAR, *LPCCHAR; typedef const DOUBLE CDOUBLE, *PCDOUBLE, *LPCDOUBLE; typedef const DWORD CDWORD, *PCDWORD, *LPCDWORD; typedef const FLOAT CFLOAT, *PCFLOAT, *LPCFLOAT; typedef const INT CINT, *PCINT, *LPCINT; typedef const LONG CLONG, *PCLONG, *LPCLONG; typedef const SCHAR CSCHAR, *PCSCHAR, *LPCSCHAR; typedef const SHORT CSHORT, *PCSHORT, *LPCSHORT; typedef const UCHAR CUCHAR, *PCUCHAR, *LPCUCHAR; typedef const UINT CUINT, *PCUINT, *LPCUINT; typedef const ULONG CULONG, *PCULONG, *LPCULONG; typedef const USHORT CUSHORT, *PCUSHORT, *LPCUSHORT; typedef const VOID CVOID, *PCVOID, *LPCVOID; typedef const WORD CWORD, *PCWORD, *LPCWORD; /* Integer types */ typedef signed char INT8, *PINT8; typedef unsigned char UINT8, *PUINT8; typedef signed short INT16, *PINT16; typedef unsigned short UINT16, *PUINT16; typedef signed int INT32, *PINT32; typedef unsigned int UINT32, *PUINT32; typedef signed long long INT64, *PINT64; typedef unsigned long long UINT64, *PUINT64; /* 64-bit types */ typedef long double DOUBLE64, *PDOUBLE64; typedef long double LDOUBLE, *PLDOUBLE; typedef long long LONG64, *PLONG64; typedef long long LONGLONG, *PLONGLONG; typedef unsigned long long ULONGLONG, *PULONGLONG; /* Signed 32-bit wide types */ typedef signed int LONG32, *PLONG32; /* Unsigned 32-bit wide types */ typedef unsigned int DWORD32, *PDWORD32; typedef unsigned int ULONG32, *PULONG32; /* Unsigned 64-bit wide types */ typedef unsigned long long DWORD64, *PDWORD64; typedef unsigned long long ULONG64, *PULONG64; /* Pointer size guaranteed types */ #if defined(_XT64) typedef long long INT_PTR, *PINT_PTR; typedef unsigned long long UINT_PTR, *PUINT_PTR; typedef long long LONG_PTR, *PLONG_PTR; typedef unsigned long long ULONG_PTR, *PULONG_PTR; typedef unsigned long long POINTER_64_INT; #else typedef int INT_PTR, *PINT_PTR; typedef unsigned int UINT_PTR, *PUINT_PTR; typedef long LONG_PTR, *PLONG_PTR; typedef unsigned long ULONG_PTR, *PULONG_PTR; typedef unsigned long POINTER_64_INT; #endif /* Flag (bitfield) types */ typedef BYTE FCHAR; typedef DWORD FLONG; typedef WORD FSHORT; /* SIZE_T types */ typedef ULONG_PTR SIZE_T, *PSIZE_T; typedef LONG_PTR SSIZE_T, *PSSIZE_T; /* Pointer to PVOID */ typedef PVOID *PPVOID; /* Polymorphic values types */ typedef SLONG HPARAM, HRESULT; typedef LONG_PTR LPARAM, LRESULT; typedef UINT_PTR WPARAM, WRESULT; /* Handle types */ typedef VOID *HANDLE, **PHANDLE; typedef HANDLE *SPHANDLE, *LPHANDLE; /* XT status types */ typedef LONG XTSTATUS, *PXTSTATUS; /* ANSI character types */ typedef CHAR *PCH, *LPCH; typedef CHAR *PCCH, *LPCCH; typedef CHAR *PSTR, *LPSTR, *NPSTR; typedef PSTR *PZPSTR; typedef const PSTR *PCZPSTR; typedef const CHAR *PCSTR, *LPCSTR; typedef PCSTR *PZPCSTR; /* ASCIIZ character types */ typedef CHAR SZ, *PSZ; typedef const CHAR CSZ, *PCSZ; /* UNICODE character types */ typedef wchar WCHAR, *PWCHAR; typedef WCHAR *PWCH, *LPWCH; typedef const WCHAR *PCWCH, *LPCWCH; typedef WCHAR *PWSTR, *LPWSTR, *NWPSTR; typedef PWSTR *PZPWSTR; typedef const PWSTR *PCZPWSTR; typedef WCHAR *PUWSTR, *LPUWSTR; typedef const WCHAR *PCWSTR, *LPCWSTR; typedef PCWSTR *PZPCWSTR; typedef const WCHAR *PCUWSTR, *LPCUWSTR; /* Neutral character types */ typedef WCHAR TBYTE, *PTBYTE; typedef WCHAR TCHAR, *PTCHAR; typedef LPWSTR LP; typedef LPWSTR PTCH, LPTCH; typedef LPWSTR PTSTR, LPTSTR; typedef LPCWSTR PCTSTR, LPCTSTR; typedef LPUWSTR PUTSTR, LPUTSTR; typedef LPCUWSTR PCUTSTR, LPCUTSTR; /* Variadic ABI types */ typedef __builtin_va_list VA_LIST, *PVA_LIST; /* 128-bit floats structure */ typedef struct _FLOAT128 { LONGLONG LowPart; LONGLONG HighPart; } FLOAT128, *PFLOAT128; /* 64-bit floating point union */ typedef union _LARGE_DOUBLE { struct { ULONG LowPart; ULONG HighPart; } u; DOUBLE DoublePart; ULONGLONG QuadPart; } LARGE_DOUBLE, *PLARGE_DOUBLE; /* 64-bit signed integer union */ typedef union _LARGE_INTEGER { struct { ULONG LowPart; LONG HighPart; }; struct { ULONG LowPart; LONG HighPart; } u; LONGLONG QuadPart; } LARGE_INTEGER, *PLARGE_INTEGER; /* 64-bit unsigned integer union */ typedef union _ULARGE_INTEGER { struct { ULONG LowPart; ULONG HighPart; }; struct { ULONG LowPart; ULONG HighPart; } u; ULONGLONG QuadPart; } ULARGE_INTEGER, *PULARGE_INTEGER; /* Counted string structure */ typedef struct _STRING { USHORT Length; USHORT MaximumLength; PCHAR Buffer; } STRING, *PSTRING; /* 32-bit counted string structure */ typedef struct _STRING32 { USHORT Length; USHORT MaximumLength; ULONG Buffer; } STRING32, *PSTRING32; /* 64-bit counted string structure */ typedef struct _STRING64 { USHORT Length; USHORT MaximumLength; ULONGLONG Buffer; } STRING64, *PSTRING64; /* Constant counted string structure */ typedef struct _CSTRING { USHORT Length; USHORT MaximumLength; PCCHAR Buffer; } CSTRING, *PCSTRING; /* ANSI string structure */ typedef struct _ANSI_STRING { USHORT Length; USHORT MaximumLength; PSTR Buffer; } ANSI_STRING, *PANSI_STRING; typedef const ANSI_STRING *PCANSI_STRING; /* 32-bit ANSI string structure */ typedef struct _ANSI_STRING32 { USHORT Length; USHORT MaximumLength; ULONG Buffer; } ANSI_STRING32, *PANSI_STRING32; typedef const ANSI_STRING32 *PCANSI_STRING32; /* 64-bit ANSI string structure */ typedef struct _ANSI_STRING64 { USHORT Length; USHORT MaximumLength; ULONGLONG Buffer; } ANSI_STRING64, *PANSI_STRING64; typedef const ANSI_STRING64 *PCANSI_STRING64; /* UNICODE string structure */ typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; typedef const UNICODE_STRING *PCUNICODE_STRING; /* 32-bit UNICODE string structure */ typedef struct _UNICODE_STRING32 { USHORT Length; USHORT MaximumLength; ULONG Buffer; } UNICODE_STRING32, *PUNICODE_STRING32; typedef const UNICODE_STRING32 *PCUNICODE_STRING32; /* 64-bit UNICODE string structure */ typedef struct _UNICODE_STRING64 { USHORT Length; USHORT MaximumLength; ULONGLONG Buffer; } UNICODE_STRING64, *PUNICODE_STRING64; typedef const UNICODE_STRING64 *PCUNICODE_STRING64; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_XTTYPES_H */ ================================================ FILE: sdk/xtdk/xtuefi.h ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: sdk/xtdk/xtuefi.h * DESCRIPTION: XT UEFI support * DEVELOPERS: Rafal Kupiec */ #ifndef __XTDK_XTUEFI_H #define __XTDK_XTUEFI_H #include #include #include #include /* EFI ACPI Small Item Descriptor Name */ #define EFI_ACPI_SMALL_IRQ_DESCRIPTOR_NAME 0x04 #define EFI_ACPI_SMALL_DMA_DESCRIPTOR_NAME 0x05 #define EFI_ACPI_SMALL_START_DEPENDENT_DESCRIPTOR_NAME 0x06 #define EFI_ACPI_SMALL_END_DEPENDENT_DESCRIPTOR_NAME 0x07 #define EFI_ACPI_SMALL_IO_PORT_DESCRIPTOR_NAME 0x08 #define EFI_ACPI_SMALL_FIXED_IO_PORT_DESCRIPTOR_NAME 0x09 #define EFI_ACPI_SMALL_VENDOR_DEFINED_DESCRIPTOR_NAME 0x0E #define EFI_ACPI_SMALL_END_TAG_DESCRIPTOR_NAME 0x0F /* EFI ACPI Large Item Descriptor Name */ #define EFI_ACPI_LARGE_24_BIT_MEMORY_RANGE_DESCRIPTOR_NAME 0x01 #define EFI_ACPI_LARGE_VENDOR_DEFINED_DESCRIPTOR_NAME 0x04 #define EFI_ACPI_LARGE_32_BIT_MEMORY_RANGE_DESCRIPTOR_NAME 0x05 #define EFI_ACPI_LARGE_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR_NAME 0x06 #define EFI_ACPI_LARGE_DWORD_ADDRESS_SPACE_DESCRIPTOR_NAME 0x07 #define EFI_ACPI_LARGE_WORD_ADDRESS_SPACE_DESCRIPTOR_NAME 0x08 #define EFI_ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME 0x09 #define EFI_ACPI_LARGE_QWORD_ADDRESS_SPACE_DESCRIPTOR_NAME 0x0A /* EFI ACPI Small Item Descriptor Values */ #define EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR 0x22 #define EFI_ACPI_IRQ_DESCRIPTOR 0x23 #define EFI_ACPI_DMA_DESCRIPTOR 0x2A #define EFI_ACPI_START_DEPENDENT_DESCRIPTOR 0x30 #define EFI_ACPI_START_DEPENDENT_EX_DESCRIPTOR 0x31 #define EFI_ACPI_END_DEPENDENT_DESCRIPTOR 0x38 #define EFI_ACPI_IO_PORT_DESCRIPTOR 0x47 #define EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR 0x4B #define EFI_ACPI_END_TAG_DESCRIPTOR 0x79 /* EFI ACPI Large Item Descriptor Values */ #define EFI_ACPI_24_BIT_MEMORY_RANGE_DESCRIPTOR 0x81 #define EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR 0x85 #define EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR 0x86 #define EFI_ACPI_ADDRESS32_SPACE_DESCRIPTOR 0x87 #define EFI_ACPI_ADDRESS16_SPACE_DESCRIPTOR 0x88 #define EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR 0x89 #define EFI_ACPI_ADDRESS64_SPACE_DESCRIPTOR 0x8A /* EFI ACPI Resource Types */ #define EFI_ACPI_ADDRESS_SPACE_TYPE_MEMORY 0x00 #define EFI_ACPI_ADDRESS_SPACE_TYPE_IO 0x01 #define EFI_ACPI_ADDRESS_SPACE_TYPE_BUS_NUMBER 0x02 /* EFI service signatures */ #define EFI_BOOT_SERVICES_SIGNATURE 0x56524553544f4f42 #define EFI_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552 #define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249 /* Caching types for the memory range */ #define EFI_MEMORY_UC 0x0000000000000001 #define EFI_MEMORY_WC 0x0000000000000002 #define EFI_MEMORY_WT 0x0000000000000004 #define EFI_MEMORY_WB 0x0000000000000008 #define EFI_MEMORY_UCE 0x0000000000000010 /* Physical memory protection on range */ #define EFI_MEMORY_WP 0x0000000000001000 #define EFI_MEMORY_RP 0x0000000000002000 #define EFI_MEMORY_XP 0x0000000000004000 #define EFI_MEMORY_RO 0x0000000000020000 /* Physical memory persistence attribute */ #define EFI_MEMORY_NV 0x0000000000008000 /* Memory region provides higher reliability relative to other memory in the system */ #define EFI_MEMORY_MORE_RELIABLE 0x0000000000010000 /* Specific-purpose memory (SPM) */ #define EFI_MEMORY_SP 0x0000000000040000 /* Memory region capable of being protected with the CPU's cryptography */ #define EFI_MEMORY_CPU_CRYPTO 0x0000000000080000 /* EFI Runtime memory attribute */ #define EFI_MEMORY_RUNTIME 0x8000000000000000 /* EFI Pages related definitions */ #define EFI_PAGE_SIZE 4096 #define EFI_PAGE_MASK 0xFFF #define EFI_PAGE_SHIFT 12 /* EFI open protocol */ #define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001 #define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002 #define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004 #define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008 #define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 #define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020 /* EFI capsule flags */ #define EFI_CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000 #define EFI_CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 #define EFI_CAPSULE_FLAGS_INITIATE_RESET 0x00040000 /* EFI variables related definitions */ #define EFI_VARIABLE_NON_VOLATILE 0x00000001 #define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 #define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 #define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008 #define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010 #define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020 #define EFI_VARIABLE_APPEND_WRITE 0x00000040 /* Maximum EFI variable size */ #define EFI_MAXIMUM_VARIABLE_SIZE 1024 /* EFI event types */ #define EFI_EVENT_EFI_SIGNAL_MASK 0x000000FF #define EFI_EVENT_NOTIFY_WAIT 0x00000100 #define EFI_EVENT_NOTIFY_SIGNAL 0x00000200 #define EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 #define EFI_EVENT_RUNTIME_CONTEXT 0x20000000 #define EFI_EVENT_RUNTIME 0x40000000 #define EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 #define EFI_EVENT_TIMER 0x80000000 /* EFI disk signature type */ #define EFI_DISK_SIGNATURE_TYPE_MBR 0x01 #define EFI_DISK_SIGNATURE_TYPE_GPT 0x02 /* EFI device path types */ #define EFI_HARDWARE_DEVICE_PATH 0x01 #define EFI_ACPI_DEVICE_PATH 0x02 #define EFI_MESSAGING_DEVICE_PATH 0x03 #define EFI_MEDIA_DEVICE_PATH 0x04 #define EFI_BBS_DEVICE_PATH 0x05 #define EFI_END_DEVICE_PATH 0x7F /* EFI hardware device path subtypes */ #define EFI_HARDWARE_PCI_DP 0x01 #define EFI_HARDWARE_PCCARD_DP 0x02 #define EFI_HARDWARE_MEMMAP_DP 0x03 #define EFI_HARDWARE_VENDOR_DP 0x04 #define EFI_HARDWARE_CONTROLLER_DP 0x05 /* EFI ACPI device path subtypes */ #define EFI_ACPI_DP 0x01 #define EFI_ACPI_EXPANDED_DP 0x02 /* EFI messaging device path subtypes */ #define EFI_MESSAGING_ATAPI_DP 0x01 #define EFI_MESSAGING_SCSI_DP 0x02 #define EFI_MESSAGING_FIBRECHANNEL_DP 0x03 #define EFI_MESSAGING_1394_DP 0x04 #define EFI_MESSAGING_USB_DP 0x05 #define EFI_MESSAGING_I2O_DP 0x06 #define EFI_MESSAGING_INFINIBAND_DP 0x09 #define EFI_MESSAGING_VENDOR_DP 0x0A #define EFI_MESSAGING_MAC_ADDR_DP 0x0B #define EFI_MESSAGING_IPv4_DP 0x0C #define EFI_MESSAGING_IPv6_DP 0x0D #define EFI_MESSAGING_UART_DP 0x0E #define EFI_MESSAGING_USB_CLASS_DP 0x0F #define EFI_MESSAGING_USB_WWID_DP 0x10 #define EFI_MESSAGING_DEVICE_LOGICAL_UNIT_DP 0x11 #define EFI_MESSAGING_SATA_DP 0x12 #define EFI_MESSAGING_VLAN_DP 0x14 #define EFI_MESSAGING_FIBRECHANNELEX_DP 0x15 #define EFI_MESSAGING_URI_DP 0x18 /* EFI media device path subtypes */ #define EFI_MEDIA_HARDDRIVE_DP 0x01 #define EFI_MEDIA_CDROM_DP 0x02 #define EFI_MEDIA_VENDOR_DP 0x03 #define EFI_MEDIA_FILEPATH_DP 0x04 #define EFI_MEDIA_PROTOCOL_DP 0x05 #define EFI_MEDIA_PIWG_FW_FILE_DP 0x06 #define EFI_MEDIA_PIWG_FW_VOL_DP 0x07 #define EFI_MEDIA_RELATIVE_OFFSET_RANGE_DP 0x08 #define EFI_MEDIA_RAMDISK_DP 0x09 /* DeviceType definitions according to BBS specification */ #define EFI_BBS_TYPE_FLOPPY 0x01 #define EFI_BBS_TYPE_HARDDRIVE 0x02 #define EFI_BBS_TYPE_CDROM 0x03 #define EFI_BBS_TYPE_PCMCIA 0x04 #define EFI_BBS_TYPE_USB 0x05 #define EFI_BBS_TYPE_EMBEDDED_NETWORK 0x06 #define EFI_BBS_TYPE_DEV 0x80 #define EFI_BBS_TYPE_UNKNOWN 0xFF /* EFI end device path subtypes */ #define EFI_END_INSTANCE_DP 0x01 #define EFI_END_UNPACKED_DP 0x7F #define EFI_END_ENTIRE_DP 0xFF /* EFI file open modes */ #define EFI_FILE_MODE_READ 0x0000000000000001 #define EFI_FILE_MODE_WRITE 0x0000000000000002 #define EFI_FILE_MODE_CREATE 0x8000000000000000 /* EFI file attributes */ #define EFI_FILE_READ_ONLY 0x0000000000000001 #define EFI_FILE_HIDDEN 0x0000000000000002 #define EFI_FILE_SYSTEM 0x0000000000000004 #define EFI_FILE_RESERVIED 0x0000000000000008 #define EFI_FILE_DIRECTORY 0x0000000000000010 #define EFI_FILE_ARCHIVE 0x0000000000000020 #define EFI_FILE_VALID_ATTR 0x0000000000000037 /* EFI PCI attributes */ #define EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x00001 #define EFI_PCI_ATTRIBUTE_ISA_IO 0x00002 #define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO 0x00004 #define EFI_PCI_ATTRIBUTE_VGA_MEMORY 0x00008 #define EFI_PCI_ATTRIBUTE_VGA_IO 0x00010 #define EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO 0x00020 #define EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO 0x00040 #define EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x00080 #define EFI_PCI_ATTRIBUTE_IO 0x00100 #define EFI_PCI_ATTRIBUTE_MEMORY 0x00200 #define EFI_PCI_ATTRIBUTE_BUS_MASTER 0x00400 #define EFI_PCI_ATTRIBUTE_MEMORY_CACHED 0x00800 #define EFI_PCI_ATTRIBUTE_MEMORY_DISABLE 0x01000 #define EFI_PCI_ATTRIBUTE_EMBEDDED_DEVICE 0x02000 #define EFI_PCI_ATTRIBUTE_EMBEDDED_ROM 0x04000 #define EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x08000 #define EFI_PCI_ATTRIBUTE_ISA_IO_16 0x10000 #define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 #define EFI_PCI_ATTRIBUTE_VGA_IO_16 0x40000 /* EFI UART attributes */ #define EFI_UART_CLEAR_TO_SEND 0x0010 #define EFI_UART_DATA_SET_READY 0x0020 #define EFI_UART_RING_INDICATE 0x0040 #define EFI_UART_CARRIER_DETECT 0x0080 #define EFI_UART_REQUEST_TO_SEND 0x0002 #define EFI_UART_DATA_TERMINAL_READY 0x0001 #define EFI_UART_INPUT_BUFFER_EMPTY 0x0100 #define EFI_UART_OUTPUT_BUFFER_EMPTY 0x0200 #define EFI_UART_HARDWARE_LOOPBACK_ENABLE 0x1000 #define EFI_UART_SOFTWARE_LOOPBACK_ENABLE 0x2000 #define EFI_UART_HARDWARE_FLOW_CONTROL_ENABLE 0x4000 /* EFI Simple Network protocol */ #define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01 #define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02 #define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04 #define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08 #define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10 /* EFI task priority levels */ #define EFI_TPL_APPLICATION 4 #define EFI_TPL_CALLBACK 8 #define EFI_TPL_NOTIFY 16 #define EFI_TPL_HIGH_LEVEL 31 /* EFI Processor StatusFlag bits */ #define EFI_PROCESSOR_AS_BSP_BIT 0x00000001 #define EFI_PROCESSOR_ENABLED_BIT 0x00000002 #define EFI_PROCESSOR_HEALTH_STATUS_BIT 0x00000004 /* EFI list of failed CPUs termination */ #define EFI_PROCESSOR_END_OF_LIST 0xFFFFFFFF /* EFI text background color definitions */ #define EFI_TEXT_BGCOLOR_BLACK 0x00 #define EFI_TEXT_BGCOLOR_BLUE 0x10 #define EFI_TEXT_BGCOLOR_GREEN 0x20 #define EFI_TEXT_BGCOLOR_CYAN 0x30 #define EFI_TEXT_BGCOLOR_RED 0x40 #define EFI_TEXT_BGCOLOR_MAGENTA 0x50 #define EFI_TEXT_BGCOLOR_BROWN 0x60 #define EFI_TEXT_BGCOLOR_LIGHTGRAY 0x70 /* EFI text foreground color definitions */ #define EFI_TEXT_FGCOLOR_BLACK 0x00 #define EFI_TEXT_FGCOLOR_BLUE 0x01 #define EFI_TEXT_FGCOLOR_GREEN 0x02 #define EFI_TEXT_FGCOLOR_CYAN 0x03 #define EFI_TEXT_FGCOLOR_RED 0x04 #define EFI_TEXT_FGCOLOR_MAGENTA 0x05 #define EFI_TEXT_FGCOLOR_BROWN 0x06 #define EFI_TEXT_FGCOLOR_LIGHTGRAY 0x07 #define EFI_TEXT_FGCOLOR_DARKGRAY 0x08 #define EFI_TEXT_FGCOLOR_LIGHTBLUE 0x09 #define EFI_TEXT_FGCOLOR_LIGHTGREEN 0x0A #define EFI_TEXT_FGCOLOR_LIGHTCYAN 0x0B #define EFI_TEXT_FGCOLOR_LIGHTRED 0x0C #define EFI_TEXT_FGCOLOR_LIGHTMAGENTA 0x0D #define EFI_TEXT_FGCOLOR_YELLOW 0x0E #define EFI_TEXT_FGCOLOR_WHITE 0x0F /* EFI text box character definitions */ #define EFI_TEXT_BOX_HORIZONTAL 0x2500 #define EFI_TEXT_BOX_VERTICAL 0x2502 #define EFI_TEXT_BOX_DOWN_RIGHT 0x250C #define EFI_TEXT_BOX_DOWN_LEFT 0x2510 #define EFI_TEXT_BOX_UP_RIGHT 0x2518 #define EFI_TEXT_BOX_UP_LEFT 0x2514 #define EFI_TEXT_BOX_VERTICAL_RIGHT 0x251C #define EFI_TEXT_BOX_VERTICAL_LEFT 0x2524 #define EFI_TEXT_BOX_FULL_BLOCK 0x2588 #define EFI_TEXT_BOX_LIGHT_BLOCK 0x2591 /* EFI OS indication bits */ #define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001ULL /* EFI protocols GUIDs */ #define EFI_BLOCK_IO_PROTOCOL_GUID {0x964E5B21, 0x6459, 0x11D2, {0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B}} #define EFI_BLOCK_IO2_PROTOCOL_GUID {0xA77B2472, 0xE282, 0x4E9F, {0xA2, 0x45, 0xC2, 0xC0, 0xE2, 0x7B, 0xBC, 0xC1}} #define EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID {0x3BC1B285, 0x8A15, 0x4A82, {0xAA, 0xBF, 0x4D, 0x7D, 0x13, 0xFB, 0x32, 0x65}} #define EFI_COMPONENT_NAME_PROTOCOL_GUID {0x107A772C, 0xD5E1, 0x11D4, {0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}} #define EFI_COMPONENT_NAME2_PROTOCOL_GUID {0x6A7A5CFF, 0xE8D9, 0x4F70, {0xBA, 0xDA, 0x75, 0xAB, 0x30, 0x25, 0xCE, 0x14}} #define EFI_DEBUG_IMAGE_INFO_TABLE_GUID {0x49152E77, 0x1ADA, 0x4764, {0xB7, 0xA2, 0x7A, 0xFE, 0xFE, 0xD9, 0x5E, 0x8B}} #define EFI_DEBUG_SUPPORT_PROTOCOL_GUID {0x2755590C, 0x6F3C, 0x42FA, {0x9E, 0xA4, 0xA3, 0xBA, 0x54, 0x3C, 0xDA, 0x25}} #define EFI_DEVICE_IO_PROTOCOL_GUID {0xAF6AC311, 0x84C3, 0x11D2, {0x8E, 0x3C, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B}} #define EFI_DEVICE_PATH_PROTOCOL_GUID {0x09576E91, 0x6D3F, 0x11D2, {0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B}} #define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID {0x05C99A21, 0xC70F, 0x4AD2, {0x8A, 0x5F, 0x35, 0xDF, 0x33, 0x43, 0xF5, 0x1E}} #define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID {0x8B843E20, 0x8132, 0x4852, {0x90, 0xCC, 0x55, 0x1A, 0x4E, 0x4A, 0x7F, 0x1C}} #define EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID {0x0379BE4E, 0xD706, 0x437D, {0xB0, 0x37, 0xED, 0xB8, 0x2F, 0xB7, 0x72, 0xA4}} #define EFI_DISK_IO_PROTOCOL_GUID {0xCE345171, 0xBA0B, 0x11D2, {0x8E, 0x4F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B}} #define EFI_DISK_IO2_PROTOCOL_GUID {0x151C8EAE, 0x7F2C, 0x472C, {0x9E, 0x54, 0x98, 0x28, 0x19, 0x4F, 0x6A, 0x88}} #define EFI_DRIVER_BINDING_PROTOCOL_GUID {0x18A031AB, 0xB443, 0x4D1A, {0xA5, 0xC0, 0x0C, 0x09, 0x26, 0x1E, 0x9F, 0x71}} #define EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL_GUID {0xB1EE129E, 0xDA36, 0x4181, {0x91, 0xF8, 0x04, 0xA4, 0x92, 0x37, 0x66, 0xA7}} #define EFI_EBC_INTERPRETER_PROTOCOL_GUID {0x13AC6DD1, 0x73D0, 0x11D4, {0xB0, 0x6B, 0x00, 0xAA, 0x00, 0xBD, 0x6D, 0xE7}} #define EFI_EDID_ACTIVE_PROTOCOL_GUID {0xBD8C1056, 0x9F36, 0x44EC, {0x92, 0xA8, 0xA6, 0x33, 0x7F, 0x81, 0x79, 0x86}} #define EFI_EDID_DISCOVERED_PROTOCOL_GUID {0x1C0C34F6, 0xD380, 0x41FA, {0xA0, 0x49, 0x8a, 0xD0, 0x6C, 0x1A, 0x66, 0xAA}} #define EFI_EDID_OVERRIDE_PROTOCOL_GUID {0x48ECB431, 0xFB72, 0x45C0, {0xA9, 0x22, 0xF4, 0x58, 0xFE, 0x04, 0x0B, 0xD5}} #define EFI_FILE_INFO_PROTOCOL_GUID {0x09576E92, 0x6D3F, 0x11D2, {0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B}} #define EFI_FPSWA_PROTOCOL_GUID {0xC41B6531, 0x97B9, 0x11D3, {0x9A, 0x29, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}} #define EFI_FRAMEWORK_MP_SERVICES_PROTOCOL_GUID {0xF33261E7, 0x23CB, 0x11D5, {0xBD, 0x5C, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81}} #define EFI_GLOBAL_VARIABLE_GUID {0x8BE4DF61, 0x93CA, 0x11D2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C}} #define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID {0x9042A9DE, 0x23DC, 0x4A38, {0x96, 0xFB, 0x7A, 0xDE, 0xD0, 0x80, 0x51, 0x6A}} #define EFI_HASH_PROTOCOL_GUID {0xC5184932, 0xDBA5, 0x46DB, {0xA5, 0xBA, 0xCC, 0x0B, 0xDA, 0x9C, 0x14, 0x35}} #define EFI_LEGACY_BIOS_PROTOCOL_GUID {0xDB9A1E3D, 0x45CB, 0x4ABB, {0x85, 0x3B, 0xE5, 0x38, 0x7F, 0xDB, 0x2E, 0x2D}} #define EFI_LOAD_FILE_PROTOCOL_GUID {0x56EC3091, 0x954C, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B}} #define EFI_LOADED_IMAGE_PROTOCOL_GUID {0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B}} #define EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID {0xBC62157E, 0x3E33, 0x4FEC, {0x99, 0x20, 0x2D, 0x3B, 0x36, 0xD7, 0x50, 0xDF}} #define EFI_MP_SERVICES_PROTOCOL_GUID {0x3FDDA605, 0xA76E, 0x4F46, {0xAD, 0x29, 0x12, 0xF4, 0x53, 0x1B, 0x3D, 0x08}} #define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID {0xE18541CD, 0xF755, 0x4f73, {0x92, 0x8D, 0x64, 0x3C, 0x8A, 0x79, 0xB2, 0x29}} #define EFI_PCI_IO_PROTOCOL_GUID {0x4CF5B200, 0x68B8, 0x4CA5, {0x9E, 0xEC, 0xB2, 0x3E, 0x3F, 0x50, 0x02, 0x9A}} #define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID {0x2F707EBB, 0x4A1A, 0x11d4, {0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}} #define EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL_GUID {0x6B30C738, 0xA391, 0x11D4, {0x9A, 0x3B, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}} #define EFI_PXE_BASE_CODE_PROTOCOL_GUID {0x03C4E603, 0xAC28, 0x11D3, {0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3D, 0xC1, 0x4D}} #define EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_GUID {0x245DCA21, 0xFB7F, 0x11D3, {0x8F, 0x01, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B}} #define EFI_RNG_PROTOCOL_GUID {0x3152BCA5, 0xEADE, 0x433D, {0x86, 0x2E, 0xC0, 0x1C, 0xDC, 0x29, 0x1F, 0x44}} #define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID {0x964E5B22, 0x6459, 0x11D2, {0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B}} #define EFI_SIMPLE_NETWORK_PROTOCOL_GUID {0xA19832B9, 0xAC25, 0x11D3, {0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}} #define EFI_SIMPLE_POINTER_PROTOCOL_GUID {0x31878C87, 0x0B75, 0x11D5, {0x9A, 0x4F, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}} #define EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID {0x387477C1, 0x69C7, 0x11D2, {0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B}} #define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID {0xDD9E7534, 0x7762, 0x4698, {0x8C, 0x14, 0xF5, 0x85, 0x17, 0xA6, 0x25, 0xAA}} #define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID {0x387477C2, 0x69C7, 0x11D2, {0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B}} #define EFI_UART_IO_PROTOCOL_GUID {0xBB25CF6F, 0xF1D4, 0x11D2, {0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0xFD}} #define EFI_UNICODE_COLLATION_PROTOCOL_GUID {0x1D85CD7F, 0xF43D, 0x11D2, {0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}} #define EFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL_GUID {0x982C298B, 0xF4FA, 0x41CB, {0xB8, 0x38, 0x77, 0xAA, 0x68, 0x8F, 0xB8, 0x39}} /* EFI Configuration Tables GUIDs */ #define EFI_CONFIG_TABLE_ACPI_TABLE_GUID {0xEB9D2D30, 0x2D88, 0x11D3, {0x9A, 0x16, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}} #define EFI_CONFIG_TABLE_ACPI20_TABLE_GUID {0x8868E871, 0xE4F1, 0x11D3, {0xBC, 0x22, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81}} #define EFI_CONFIG_TABLE_DTB_TABLE_GUID {0xB1B621D5, 0xF19C, 0x41A5, {0x83, 0x0B, 0xD9, 0x15, 0x2C, 0x69, 0xAA, 0xE0}} #define EFI_CONFIG_TABLE_MPS_TABLE_GUID {0xEB9D2D2F, 0x2D88, 0x11D3, {0x9A, 0x16, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}} #define EFI_CONFIG_TABLE_SAL_SYSTEM_TABLE_GUID {0xED9D2D32, 0x2D88, 0x11D3, {0x9A, 0x16, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}} #define EFI_CONFIG_TABLE_SMBIOS_TABLE_GUID {0xEB9D2D31, 0x2D88, 0x11D3, {0x9A, 0x16, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}} #define EFI_CONFIG_TABLE_SMBIOS3_TABLE_GUID {0xF2FD1544, 0x9794, 0x4A2C, {0x99, 0x2E, 0xE5, 0xBB, 0xCf, 0x20, 0xE3, 0x94}} /* C/C++ specific code */ #ifndef __XTOS_ASSEMBLER__ /* Basic UEFI types */ typedef PVOID EFI_EVENT, *PEFI_EVENT; typedef PVOID EFI_HANDLE, *PEFI_HANDLE; typedef UINT64 EFI_LBA, *PEFI_LBA; typedef UINT64 EFI_PHYSICAL_ADDRESS, *PEFI_PHYSICAL_ADDRESS; typedef UINT_PTR EFI_STATUS, *PEFI_STATUS; typedef UINT_PTR EFI_TPL, *PEFI_TPL; typedef UINT64 EFI_VIRTUAL_ADDRESS, *PEFI_VIRTUAL_ADDRESS; /* Enumeration list of EFI memory allocation types */ typedef enum _EFI_ALLOCATE_TYPE { AllocateAnyPages, AllocateMaxAddress, AllocateAddress, MaxAllocateType } EFI_ALLOCATE_TYPE, *PEFI_ALLOCATE_TYPE; /* Enumeration list of reset types */ typedef enum _EFI_RESET_TYPE { EfiResetCold, EfiResetWarm, EfiResetShutdown } EFI_RESET_TYPE, *PEFI_RESET_TYPE; /* Enumeration list of timer delay types */ typedef enum _EFI_TIMER_DELAY { TimerCancel, TimerPeriodic, TimerRelative, TimerTypeMax } EFI_TIMER_DELAY, *PEFI_TIMER_DELAY; /* Enumeration list of EFI Locate Search Types */ typedef enum _EFI_LOCATE_SEARCH_TYPE { AllHandles, ByRegisterNotify, ByProtocol } EFI_LOCATE_SEARCH_TYPE, *PEFI_LOCATE_SEARCH_TYPE; /* Enumeration list of EFI Interface Types */ typedef enum _EFI_INTERFACE_TYPE { EFI_NATIVE_INTERFACE, EFI_PCODE_INTERFACE } EFI_INTERFACE_TYPE, *PEFI_INTERFACE_TYPE; /* Enumeration of memory types introduced in UEFI */ typedef enum _EFI_MEMORY_TYPE { EfiReservedMemoryType, EfiLoaderCode, EfiLoaderData, EfiBootServicesCode, EfiBootServicesData, EfiRuntimeServicesCode, EfiRuntimeServicesData, EfiConventionalMemory, EfiUnusableMemory, EfiACPIReclaimMemory, EfiACPIMemoryNVS, EfiMemoryMappedIO, EfiMemoryMappedIOPortSpace, EfiPalCode, EfiMaxMemoryType } EFI_MEMORY_TYPE, *PEFI_MEMORY_TYPE; /* Enumeration of PCI I/O protocol widths */ typedef enum _EFI_PCI_IO_PROTOCOL_WIDTH { EfiPciIoWidthUint8, EfiPciIoWidthUint16, EfiPciIoWidthUint32, EfiPciIoWidthUint64, EfiPciIoWidthFifoUint8, EfiPciIoWidthFifoUint16, EfiPciIoWidthFifoUint32, EfiPciIoWidthFifoUint64, EfiPciIoWidthFillUint8, EfiPciIoWidthFillUint16, EfiPciIoWidthFillUint32, EfiPciIoWidthFillUint64, EfiPciIoWidthMaximum } EFI_PCI_IO_PROTOCOL_WIDTH, *PEFI_PCI_IO_PROTOCOL_WIDTH; /* Enumeration of EFI PCI I/O protocol operations */ typedef enum _EFI_PCI_IO_PROTOCOL_OPERATION { EfiPciIoOperationBusMasterRead, EfiPciIoOperationBusMasterWrite, EfiPciIoOperationBusMasterCommonBuffer, EfiPciIoOperationMaximum } EFI_PCI_IO_PROTOCOL_OPERATION, *PEFI_PCI_IO_PROTOCOL_OPERATION; /* Enumeration of EFI PCI Root Bridge I/O protocol operations */ typedef enum _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION { EfiPciOperationBusMasterRead, EfiPciOperationBusMasterWrite, EfiPciOperationBusMasterCommonBuffer, EfiPciOperationBusMasterRead64, EfiPciOperationBusMasterWrite64, EfiPciOperationBusMasterCommonBuffer64, EfiPciOperationMaximum } EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION, *PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION; /* Enumeration of EFI PCI I/O protocol attribute operations */ typedef enum _EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION { EfiPciIoAttributeOperationGet, EfiPciIoAttributeOperationSet, EfiPciIoAttributeOperationEnable, EfiPciIoAttributeOperationDisable, EfiPciIoAttributeOperationSupported, EfiPciIoAttributeOperationMaximum } EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION, *PEFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION; /* Enumeration of EFI I/O widths */ typedef enum _EFI_IO_WIDTH { IO_UINT8, IO_UINT16, IO_UINT32, IO_UINT64, MMIO_COPY_UINT8, MMIO_COPY_UINT16, MMIO_COPY_UINT32, MMIO_COPY_UINT64 } EFI_IO_WIDTH, *PEFI_IO_WIDTH; /* Enumeration of EFI I/O operation types */ typedef enum _EFI_IO_OPERATION_TYPE { EfiBusMasterRead, EfiBusMasterWrite, EfiBusMasterCommonBuffer } EFI_IO_OPERATION_TYPE, *PEFI_IO_OPERATION_TYPE; /* Enumeration of EFI GOP output BLT operations */ typedef enum _EFI_GRAPHICS_OUTPUT_BLT_OPERATION { EfiBltVideoFill, EfiBltVideoToBltBuffer, EfiBltBufferToVideo, EfiBltVideoToVideo, EfiGraphicsOutputBltOperationMax } EFI_GRAPHICS_OUTPUT_BLT_OPERATION, *PEFI_GRAPHICS_OUTPUT_BLT_OPERATION; /* Enumeration of EFI GOP pixel formats */ typedef enum _EFI_GRAPHICS_PIXEL_FORMAT { PixelRedGreenBlueReserved8BitPerColor, PixelBlueGreenRedReserved8BitPerColor, PixelBitMask, PixelBltOnly, PixelFormatMax } EFI_GRAPHICS_PIXEL_FORMAT, *PEFI_GRAPHICS_PIXEL_FORMAT; /* Enumeration of EGI graphics protocols */ typedef enum _EFI_GRAPHICS_PROTOCOL { NONE, GOP, UGA } EFI_GRAPHICS_PROTOCOL, *PEFI_GRAPHICS_PROTOCOL; /* Enumeration of EFI UGA output BLT operations */ typedef enum _EFI_UNIVERSA_GRAPHICS_BLT_OPERATION { EfiUgaVideoFill, EfiUgaVideoToBltBuffer, EfiUgaBltBufferToVideo, EfiUgaVideoToVideo, EfiUgaBltMax } EFI_UNIVERSA_GRAPHICS_BLT_OPERATION, *PEFI_UNIVERSA_GRAPHICS_BLT_OPERATION; /* Enumeration of UART parity types */ typedef enum _EFI_UART_PARITY_TYPE { DefaultParity, NoParity, EvenParity, OddParity, MarkParity, SpaceParity } EFI_UART_PARITY_TYPE, *PEFI_UART_PARITY_TYPE; /* Enumeration of UART stop bit types */ typedef enum _EFI_UART_STOP_BITS_TYPE { DefaultStopBits, OneStopBit, OneFiveStopBits, TwoStopBits } EFI_UART_STOP_BITS_TYPE, *PEFI_UART_STOP_BITS_TYPE; /* Enumeration of CPU designations */ typedef enum _EFI_FRAMEWORK_CPU_DESIGNATION { EfiCpuAP, EfiCpuBSP, EfiCpuDesignationMaximum } EFI_FRAMEWORK_CPU_DESIGNATION, *PEFI_FRAMEWORK_CPU_DESIGNATION; /* Enumeration of network state */ typedef enum _EFI_SIMPLE_NETWORK_STATE { EfiSimpleNetworkStopped, EfiSimpleNetworkStarted, EfiSimpleNetworkInitialized, EfiSimpleNetworkMaxState } EFI_SIMPLE_NETWORK_STATE, *PEFI_SIMPLE_NETWORK_STATE; /* Enumeration of PXE TFTP opcodes */ typedef enum _EFI_PXE_BASE_CODE_TFTP_OPCODE { EFI_PXE_BASE_CODE_TFTP_FIRST, EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, EFI_PXE_BASE_CODE_TFTP_READ_FILE, EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY, EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE, EFI_PXE_BASE_CODE_MTFTP_READ_FILE, EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY, EFI_PXE_BASE_CODE_MTFTP_LAST } EFI_PXE_BASE_CODE_TFTP_OPCODE, *PEFI_PXE_BASE_CODE_TFTP_OPCODE; /* Enumeration of PXE functions */ typedef enum _EFI_PXE_BASE_CODE_FUNCTION { EFI_PXE_BASE_CODE_FUNCTION_FIRST, EFI_PXE_BASE_CODE_FUNCTION_DHCP, EFI_PXE_BASE_CODE_FUNCTION_DISCOVER, EFI_PXE_BASE_CODE_FUNCTION_MTFTP, EFI_PXE_BASE_CODE_FUNCTION_UDP_WRITE, EFI_PXE_BASE_CODE_FUNCTION_UDP_READ, EFI_PXE_BASE_CODE_FUNCTION_ARP, EFI_PXE_BASE_CODE_FUNCTION_IGMP, EFI_PXE_BASE_CODE_PXE_FUNCTION_LAST } EFI_PXE_BASE_CODE_FUNCTION, *PEFI_PXE_BASE_CODE_FUNCTION; /* Enumeration of PXE callback statuses */ typedef enum _EFI_PXE_BASE_CODE_CALLBACK_STATUS { EFI_PXE_BASE_CODE_CALLBACK_STATUS_FIRST, EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE, EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT, EFI_PXE_BASE_CODE_CALLBACK_STATUS_LAST } EFI_PXE_BASE_CODE_CALLBACK_STATUS, *PEFI_PXE_BASE_CODE_CALLBACK_STATUS; /* EFI routine callbacks */ typedef EFI_STATUS (*PEFI_CONVERT_POINTER)(IN UINT_PTR DebugDisposition, IN OUT PVOID *Address); typedef EFI_STATUS (*PEFI_ALLOCATE_PAGES)(IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINT_PTR NoPages, OUT PEFI_PHYSICAL_ADDRESS Memory); typedef EFI_STATUS (*PEFI_ALLOCATE_POOL)(IN EFI_MEMORY_TYPE PoolType, IN UINT_PTR Size, OUT PVOID *Buffer); typedef EFI_STATUS (*PEFI_FREE_PAGES)(IN EFI_PHYSICAL_ADDRESS Memory, IN UINT_PTR NoPages); typedef EFI_STATUS (*PEFI_FREE_POOL)(IN PVOID Buffer); typedef VOID (*PEFI_EVENT_NOTIFY)(IN EFI_EVENT Event, IN PVOID Context); typedef EFI_STATUS (*PEFI_CREATE_EVENT)(IN UINT32 Type, IN EFI_TPL NotifyTpl, IN PEFI_EVENT_NOTIFY NotifyFunction, IN PVOID NotifyContext, OUT PEFI_EVENT Event); typedef EFI_STATUS (*PEFI_GET_MEMORY_MAP)(IN OUT PUINT_PTR MemoryMapSize, IN OUT PEFI_MEMORY_DESCRIPTOR MemoryMap, OUT PUINT_PTR MapKey, OUT PUINT_PTR DescriptorSize, OUT PUINT32 DescriptorVersion); typedef EFI_STATUS (*PEFI_GET_VARIABLE)(IN PWCHAR VariableName, IN PEFI_GUID VendorGuid, OUT PUINT32 Attributes, IN OUT PUINT_PTR DataSize, OUT PVOID Data); typedef EFI_STATUS (*PEFI_GET_NEXT_HIGH_MONO_COUNT)(OUT PUINT32 HighCount); typedef EFI_STATUS (*PEFI_GET_NEXT_VARIABLE_NAME)(IN OUT PUINT_PTR VariableNameSize, IN OUT PWCHAR VariableName, IN OUT PEFI_GUID VendorGuid); typedef EFI_STATUS (*PEFI_GET_TIME)(OUT PEFI_TIME Time, OUT PEFI_TIME_CAPABILITIES Capabilities); typedef EFI_STATUS (*PEFI_SET_TIME)(IN PEFI_TIME Time); typedef EFI_STATUS (*PEFI_SET_TIMER)(IN EFI_EVENT Event, IN EFI_TIMER_DELAY Type, IN UINT64 TriggerTime); typedef EFI_STATUS (*PEFI_SIGNAL_EVENT)(IN EFI_EVENT Event); typedef EFI_STATUS (*PEFI_CLOSE_EVENT)(IN EFI_EVENT Event); typedef EFI_STATUS (*PEFI_CHECK_EVENT)(IN EFI_EVENT Event); typedef EFI_STATUS (*PEFI_CREATE_EVENT_EX)(IN UINT32 Type, IN EFI_TPL NotifyTpl, IN PEFI_EVENT_NOTIFY NotifyFunction, IN CONST PVOID NotifyContext, IN CONST PEFI_GUID EventGroup, OUT PEFI_EVENT Event); typedef EFI_STATUS (*PEFI_WAIT_FOR_EVENT)(IN UINT_PTR NumberOfEvents, IN PEFI_EVENT Event, OUT PUINT_PTR Index); typedef EFI_STATUS (*PEFI_QUERY_CAPSULE_CAPABILITIES)(IN PEFI_CAPSULE_HEADER *CapsuleHeaderArray, IN UINT_PTR CapsuleCount, OUT PUINT64 MaximumCapsuleSize, OUT PEFI_RESET_TYPE ResetType); typedef EFI_STATUS (*PEFI_QUERY_VARIABLE_INFO)(IN UINT32 Attributes, OUT PUINT64 MaximumVariableStorageSize, OUT PUINT64 RemainingVariableStorageSize, OUT PUINT64 MaximumVariableSize); typedef EFI_STATUS (*PEFI_RAISE_TPL)(IN EFI_TPL NewTpl); typedef EFI_STATUS (*PEFI_RESET_SYSTEM)(IN EFI_RESET_TYPE ResetType, IN EFI_STATUS ResetStatus, IN UINT_PTR DataSize, IN PWCHAR ResetData); typedef EFI_STATUS (*PEFI_RESTORE_TPL)(IN EFI_TPL OldTpl); typedef EFI_STATUS (*PEFI_UPDATE_CAPSULE)(IN PEFI_CAPSULE_HEADER *CapsuleHeaderArray, IN UINT_PTR CapsuleCount, IN EFI_PHYSICAL_ADDRESS ScatterGatherList); typedef EFI_STATUS (*PEFI_SET_VARIABLE)(IN PWCHAR VariableName, IN PEFI_GUID VendorGuid, IN UINT32 Attributes, IN UINT_PTR DataSize, IN PVOID Data); typedef EFI_STATUS (*PEFI_SET_VIRTUAL_ADDRESS_MAP)(IN UINT_PTR MemoryMapSize, IN UINT_PTR DescriptorSize, IN UINT32 DescriptorVersion, IN PEFI_MEMORY_DESCRIPTOR VirtualMap); typedef EFI_STATUS (*PEFI_GET_WAKEUP_TIME)(OUT BOOLEAN Enabled, OUT BOOLEAN Pending, OUT PEFI_TIME Time); typedef EFI_STATUS (*PEFI_SET_WAKEUP_TIME)(IN BOOLEAN Enable, IN PEFI_TIME Time); typedef EFI_STATUS (*PEFI_INSTALL_PROTOCOL_INTERFACE)(IN OUT PEFI_HANDLE Handle, IN PEFI_GUID Protocol, IN EFI_INTERFACE_TYPE InterfaceType, IN PVOID Interface); typedef EFI_STATUS (*PEFI_REINSTALL_PROTOCOL_INTERFACE)(IN EFI_HANDLE Handle, IN PEFI_GUID Protocol, IN PVOID OldInterface, IN PVOID NewInterface); typedef EFI_STATUS (*PEFI_UNINSTALL_PROTOCOL_INTERFACE)(IN EFI_HANDLE Handle, IN PEFI_GUID Protocol, IN PVOID Interface); typedef EFI_STATUS (*PEFI_HANDLE_PROTOCOL)(IN EFI_HANDLE Handle, IN PEFI_GUID Protocol, OUT PVOID *Interface); typedef EFI_STATUS (*PEFI_REGISTER_PROTOCOL_NOTIFY)(IN PEFI_GUID Protocol, IN EFI_EVENT Event, OUT PVOID *Registration); typedef EFI_STATUS (*PEFI_LOCATE_HANDLE)(IN EFI_LOCATE_SEARCH_TYPE SearchType, IN PEFI_GUID Protocol, IN PVOID SearchKey, IN OUT PUINT_PTR BufferSize, OUT PEFI_HANDLE Buffer); typedef EFI_STATUS (*PEFI_LOCATE_DEVICE_PATH)(IN PEFI_GUID Protocol, IN OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT PEFI_HANDLE Device); typedef EFI_STATUS (*PEFI_LOCATE_HANDLE_BUFFER)(IN EFI_LOCATE_SEARCH_TYPE SearchType, IN PEFI_GUID Protocol, IN PVOID SearchKey, IN OUT PUINT_PTR NoHandles, OUT PEFI_HANDLE *Buffer); typedef EFI_STATUS (*PEFI_LOCATE_PROTOCOL)(IN PEFI_GUID Protocol, IN PVOID Registration, OUT PVOID *Interface); typedef EFI_STATUS (*PEFI_INSTALL_CONFIGURATION_TABLE)(IN PEFI_GUID Guid, IN PVOID Table); typedef EFI_STATUS (*PEFI_IMAGE_LOAD)(IN BOOLEAN BootPolicy, IN EFI_HANDLE ParentImageHandle, IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, IN PVOID SourceBuffer, IN UINT_PTR SourceSize, OUT PEFI_HANDLE ImageHandle); typedef EFI_STATUS (*PEFI_IMAGE_UNLOAD)(IN EFI_HANDLE ImageHandle); typedef EFI_STATUS (*PEFI_IMAGE_START)(IN EFI_HANDLE ImageHandle, OUT PUINT_PTR ExitDataSize, OUT PWCHAR *ExitData); typedef EFI_STATUS (*PEFI_EXIT)(IN EFI_HANDLE ImageHandle, IN EFI_STATUS ExitStatus, IN UINT_PTR ExitDataSize, IN PWCHAR ExitData); typedef EFI_STATUS (*PEFI_EXIT_BOOT_SERVICES)(IN EFI_HANDLE ImageHandle, IN UINT_PTR MapKey); typedef EFI_STATUS (*PEFI_GET_NEXT_MONOTONIC_COUNT)(OUT PUINT64 Count); typedef EFI_STATUS (*PEFI_STALL)(IN UINT_PTR Microseconds); typedef EFI_STATUS (*PEFI_SET_WATCHDOG_TIMER)(IN UINT_PTR Timeout, IN UINT64 WatchdogCode, IN UINT_PTR DataSize, IN PWCHAR WatchdogData); typedef EFI_STATUS (*PEFI_CONNECT_CONTROLLER)(IN EFI_HANDLE ControllerHandle, IN PEFI_HANDLE DriverImageHandle, IN PEFI_DEVICE_PATH_PROTOCOL RemainingDevicePath, IN BOOLEAN Recursive); typedef EFI_STATUS (*PEFI_DISCONNECT_CONTROLLER)(IN EFI_HANDLE ControllerHandle, IN EFI_HANDLE DriverImageHandle, IN EFI_HANDLE ChildHandle); typedef EFI_STATUS (*PEFI_OPEN_PROTOCOL)(IN EFI_HANDLE Handle, IN PEFI_GUID Protocol, OUT PVOID *Interface, IN EFI_HANDLE AgentHandle, IN EFI_HANDLE ControllerHandle, IN UINT32 Attributes); typedef EFI_STATUS (*PEFI_CLOSE_PROTOCOL)(IN EFI_HANDLE Handle, IN PEFI_GUID Protocol, IN EFI_HANDLE AgentHandle, IN EFI_HANDLE ControllerHandle); typedef EFI_STATUS (*PEFI_OPEN_PROTOCOL_INFORMATION)(IN EFI_HANDLE Handle, IN PEFI_GUID Protocol, OUT PEFI_OPEN_PROTOCOL_INFORMATION_ENTRY *EntryBuffer, OUT PUINT_PTR EntryCount); typedef EFI_STATUS (*PEFI_PROTOCOLS_PER_HANDLE)(IN EFI_HANDLE Handle, OUT PEFI_GUID **ProtocolBuffer, OUT PUINT_PTR ProtocolBufferCount); typedef EFI_STATUS (*PEFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES)(IN OUT PEFI_HANDLE Handle, ...); typedef EFI_STATUS (*PEFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES)(IN OUT PEFI_HANDLE Handle, ...); typedef EFI_STATUS (*PEFI_CALCULATE_CRC32)(IN PVOID Data, IN UINT_PTR DataSize, OUT PUINT32 Crc32); typedef EFI_STATUS (*PEFI_COPY_MEM)(IN OUT PVOID Destination, IN PVOID Source, IN UINT_PTR Length); typedef EFI_STATUS (*PEFI_SET_MEM)(IN OUT PVOID Buffer, IN UINT_PTR Size, IN UINT8 Value); typedef EFI_STATUS (*PEFI_INPUT_RESET)(IN PEFI_SIMPLE_TEXT_INPUT_PROTOCOL This, IN BOOLEAN ExtendedVerification); typedef EFI_STATUS (*PEFI_INPUT_READ_KEY)(IN PEFI_SIMPLE_TEXT_INPUT_PROTOCOL This, OUT PEFI_INPUT_KEY Key); typedef EFI_STATUS (*PEFI_TEXT_RESET)(IN PEFI_SIMPLE_TEXT_OUTPUT_PROTOCOL This, IN BOOLEAN ExtendedVerification); typedef EFI_STATUS (*PEFI_TEXT_OUTPUT_STRING)(IN PEFI_SIMPLE_TEXT_OUTPUT_PROTOCOL This, IN PWCHAR String); typedef EFI_STATUS (*PEFI_TEXT_TEST_STRING)(IN PEFI_SIMPLE_TEXT_OUTPUT_PROTOCOL This, IN PWCHAR String); typedef EFI_STATUS (*PEFI_TEXT_QUERY_MODE)(IN PEFI_SIMPLE_TEXT_OUTPUT_PROTOCOL This, IN UINT_PTR ModeNumber, OUT PUINT_PTR Columns, OUT PUINT_PTR Rows); typedef EFI_STATUS (*PEFI_TEXT_SET_MODE)(IN PEFI_SIMPLE_TEXT_OUTPUT_PROTOCOL This, IN UINT_PTR ModeNumber); typedef EFI_STATUS (*PEFI_TEXT_SET_ATTRIBUTE)(IN PEFI_SIMPLE_TEXT_OUTPUT_PROTOCOL This, IN UINT_PTR Attribute); typedef EFI_STATUS (*PEFI_TEXT_CLEAR_SCREEN)(IN PEFI_SIMPLE_TEXT_OUTPUT_PROTOCOL This); typedef EFI_STATUS (*PEFI_TEXT_SET_CURSOR_POSITION)(IN PEFI_SIMPLE_TEXT_OUTPUT_PROTOCOL This, IN UINT_PTR Column, IN UINT_PTR Row); typedef EFI_STATUS (*PEFI_TEXT_ENABLE_CURSOR)(IN PEFI_SIMPLE_TEXT_OUTPUT_PROTOCOL This, IN BOOLEAN Enable); typedef EFI_STATUS (*PEFI_INPUT_RESET_EX)(IN PEFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL This, IN BOOLEAN ExtendedVerification); typedef EFI_STATUS (*PEFI_INPUT_READ_KEY_EX)(IN PEFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL This, OUT PEFI_KEY_DATA KeyData); typedef EFI_STATUS (*PEFI_SET_STATE)(IN PEFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL This, IN PUINT8 KeyToggleState); typedef EFI_STATUS (*PEFI_KEY_NOTIFY_FUNCTION)(IN PEFI_KEY_DATA KeyData); typedef EFI_STATUS (*PEFI_REGISTER_KEYSTROKE_NOTIFY)(IN PEFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL This, IN PEFI_KEY_DATA KeyData, IN PEFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, OUT PVOID *NotifyHandle); typedef EFI_STATUS (*PEFI_UNREGISTER_KEYSTROKE_NOTIFY)(IN PEFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL This, IN PVOID NotificationHandle); typedef PUINT16 (*PEFI_DEVICE_PATH_TO_TEXT_NODE)(IN CONST PEFI_DEVICE_PATH_PROTOCOL DeviceNode, IN UCHAR DisplayOnly, IN UCHAR AllowShortcuts); typedef PUINT16 (*PEFI_DEVICE_PATH_TO_TEXT_PATH)(IN CONST PEFI_DEVICE_PATH_PROTOCOL DevicePath, IN UCHAR DisplayOnly, IN UCHAR AllowShortcuts); typedef PEFI_DEVICE_PATH_PROTOCOL (*PEFI_DEVICE_PATH_FROM_TEXT_NODE)(IN CONST PUINT16 TextDeviceNode); typedef PEFI_DEVICE_PATH_PROTOCOL (*PEFI_DEVICE_PATH_FROM_TEXT_PATH)(IN CONST PUINT16 TextDevicePath); typedef UINT_PTR (*PEFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE)(IN CONST PEFI_DEVICE_PATH_PROTOCOL DevicePath); typedef PEFI_DEVICE_PATH_PROTOCOL (*PEFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH)(IN CONST PEFI_DEVICE_PATH_PROTOCOL DevicePath); typedef PEFI_DEVICE_PATH_PROTOCOL (*PEFI_DEVICE_PATH_UTILS_APPEND_PATH)(IN CONST PEFI_DEVICE_PATH_PROTOCOL Src1, IN CONST PEFI_DEVICE_PATH_PROTOCOL Src2); typedef PEFI_DEVICE_PATH_PROTOCOL (*PEFI_DEVICE_PATH_UTILS_APPEND_NODE)(IN CONST PEFI_DEVICE_PATH_PROTOCOL DevicePath, IN CONST PEFI_DEVICE_PATH_PROTOCOL DeviceNode); typedef PEFI_DEVICE_PATH_PROTOCOL (*PEFI_DEVICE_PATH_UTILS_APPEND_INSTANCE)(IN CONST PEFI_DEVICE_PATH_PROTOCOL DevicePath, IN CONST PEFI_DEVICE_PATH_PROTOCOL DevicePathInstance); typedef PEFI_DEVICE_PATH_PROTOCOL (*PEFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE)(IN OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePathInstance, OUT PUINT_PTR DevicePathInstanceSize); typedef PEFI_DEVICE_PATH_PROTOCOL (*PEFI_DEVICE_PATH_UTILS_CREATE_NODE)(IN UINT8 NodeType, IN UINT8 NodeSubType, IN UINT16 NodeLength); typedef UCHAR (*PEFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE)(IN CONST PEFI_DEVICE_PATH_PROTOCOL DevicePath); typedef EFI_STATUS (*EFI_PCI_IO_PROTOCOL_POLL_IO_MEM)(IN PEFI_PCI_IO_PROTOCOL This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT8 BarIndex, IN UINT64 Offset, IN UINT64 Mask, IN UINT64 Value, IN UINT64 Delay, OUT PUINT64 Result); typedef EFI_STATUS (*EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM)(IN PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINT64 Mask, IN UINT64 Value, IN UINT64 Delay, OUT PUINT64 Result); typedef EFI_STATUS (*EFI_PCI_IO_PROTOCOL_IO_MEM)(IN PEFI_PCI_IO_PROTOCOL This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT8 BarIndex, IN UINT64 Offset, IN UINT_PTR Count, IN OUT PVOID Buffer); typedef EFI_STATUS (*EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM)(IN PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINT_PTR Count, IN OUT PVOID Buffer); typedef EFI_STATUS (*EFI_PCI_IO_PROTOCOL_CONFIG)(IN PEFI_PCI_IO_PROTOCOL This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT32 Offset, IN UINT_PTR Count, IN OUT PVOID Buffer); typedef EFI_STATUS (*EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION)(IN PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL This, OUT PVOID *Resources); typedef EFI_STATUS (*EFI_PCI_IO_PROTOCOL_COPY_MEM)(IN PEFI_PCI_IO_PROTOCOL This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT8 DestBarIndex, IN UINT64 DestOffset, IN UINT8 SrcBarIndex, IN UINT64 SrcOffset, IN UINT_PTR Count); typedef EFI_STATUS (*EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM)(IN PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT64 DestAddress, IN UINT64 SrcAddress, IN UINT_PTR Count); typedef EFI_STATUS (*EFI_PCI_IO_PROTOCOL_MAP)(IN PEFI_PCI_IO_PROTOCOL This, IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, IN PVOID HostAddress, IN OUT PUINT_PTR NumberOfBytes, OUT PEFI_PHYSICAL_ADDRESS DeviceAddress, OUT PVOID *Mapping); typedef EFI_STATUS (*EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP)(IN PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, IN PVOID HostAddress, IN OUT PUINT_PTR NumberOfBytes, OUT PEFI_PHYSICAL_ADDRESS DeviceAddress, OUT PVOID *Mapping); typedef EFI_STATUS (*EFI_PCI_IO_PROTOCOL_UNMAP)(IN PEFI_PCI_IO_PROTOCOL This, IN PVOID Mapping); typedef EFI_STATUS (*EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP)(IN PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL This, IN PVOID Mapping); typedef EFI_STATUS (*EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER)(IN PEFI_PCI_IO_PROTOCOL This, IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINT_PTR Pages, OUT PVOID *HostAddress, IN UINT64 Attributes); typedef EFI_STATUS (*EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER)(IN PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL This, IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINT_PTR Pages, IN OUT PVOID *HostAddress, IN UINT64 Attributes); typedef EFI_STATUS (*EFI_PCI_IO_PROTOCOL_FREE_BUFFER)(IN PEFI_PCI_IO_PROTOCOL This, IN UINT_PTR Pages, IN PVOID HostAddress); typedef EFI_STATUS (*EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER)(IN PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL This, IN UINT_PTR Pages, IN PVOID HostAddress); typedef EFI_STATUS (*EFI_PCI_IO_PROTOCOL_FLUSH)(IN PEFI_PCI_IO_PROTOCOL This); typedef EFI_STATUS (*EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH)(IN PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL This); typedef EFI_STATUS (*EFI_PCI_IO_PROTOCOL_GET_LOCATION)(IN PEFI_PCI_IO_PROTOCOL This, OUT PUINT_PTR SegmentNumber, OUT PUINT_PTR BusNumber, OUT PUINT_PTR DeviceNumber, OUT PUINT_PTR FunctionNumber); typedef EFI_STATUS (*EFI_PCI_IO_PROTOCOL_ATTRIBUTES)(IN PEFI_PCI_IO_PROTOCOL This, IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, IN UINT64 Attributes, OUT PUINT64 Result); typedef EFI_STATUS (*EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES)(IN PEFI_PCI_IO_PROTOCOL This, IN UINT8 BarIndex, OUT PUINT64 Supports, OUT PVOID *Resources); typedef EFI_STATUS (*EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES)(IN PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL This, OUT PUINT64 Supports, OUT PUINT64 Attributes); typedef EFI_STATUS (*EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES)(IN PEFI_PCI_IO_PROTOCOL This, IN UINT64 Attributes, IN UINT8 BarIndex, IN OUT PUINT64 Offset, IN OUT PUINT64 Length); typedef EFI_STATUS (*EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES)(IN PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL This, IN UINT64 Attributes, IN OUT PUINT64 ResourceBase, IN OUT PUINT64 ResourceLength); typedef EFI_STATUS (*PEFI_BLOCK_RESET)(IN PEFI_BLOCK_IO_PROTOCOL This, IN BOOLEAN ExtendedVerification); typedef EFI_STATUS (*PEFI_BLOCK_READ)(IN PEFI_BLOCK_IO_PROTOCOL This, IN UINT32 MediaId, IN EFI_LBA LBA, IN UINT_PTR BufferSize, OUT PVOID Buffer); typedef EFI_STATUS (*PEFI_BLOCK_WRITE)(IN PEFI_BLOCK_IO_PROTOCOL This, IN UINT32 MediaId, IN EFI_LBA LBA, IN UINT_PTR BufferSize, IN PVOID Buffer); typedef EFI_STATUS (*PEFI_BLOCK_FLUSH)(IN PEFI_BLOCK_IO_PROTOCOL This); typedef EFI_STATUS (*PEFI_BLOCK_RESET_EX)(IN PEFI_BLOCK_IO2_PROTOCOL This, IN BOOLEAN ExtendedVerification); typedef EFI_STATUS (*PEFI_BLOCK_READ_EX)(IN PEFI_BLOCK_IO2_PROTOCOL This, IN UINT32 MediaId, IN EFI_LBA LBA, IN OUT PEFI_BLOCK_IO2_TOKEN Token, IN UINT_PTR BufferSize, OUT PVOID Buffer); typedef EFI_STATUS (*PEFI_BLOCK_WRITE_EX)(IN PEFI_BLOCK_IO2_PROTOCOL This, IN UINT32 MediaId, IN EFI_LBA LBA, IN OUT PEFI_BLOCK_IO2_TOKEN Token, IN UINT_PTR BufferSize, IN PVOID Buffer); typedef EFI_STATUS (*PEFI_BLOCK_FLUSH_EX)(IN PEFI_BLOCK_IO2_PROTOCOL This, IN OUT PEFI_BLOCK_IO2_TOKEN Token); typedef EFI_STATUS (*PEFI_DISK_READ)(IN PEFI_DISK_IO_PROTOCOL This, IN UINT32 MediaId, IN UINT64 Offset, IN UINT_PTR BufferSize, OUT PVOID Buffer); typedef EFI_STATUS (*PEFI_DISK_WRITE)(IN PEFI_DISK_IO_PROTOCOL This, IN UINT32 MediaId, IN UINT64 Offset, IN UINT_PTR BufferSize, IN PVOID Buffer); typedef EFI_STATUS (*PEFI_DISK_CANCEL_EX)(IN PEFI_DISK_IO2_PROTOCOL This); typedef EFI_STATUS (*PEFI_DISK_READ_EX)(IN PEFI_DISK_IO2_PROTOCOL This, IN UINT32 MediaId, IN UINT64 Offset, IN OUT PEFI_DISK_IO2_TOKEN Token, IN UINT_PTR BufferSize, OUT PVOID Buffer); typedef EFI_STATUS (*PEFI_DISK_WRITE_EX)(IN PEFI_DISK_IO2_PROTOCOL This, IN UINT32 MediaId, IN UINT64 Offset, IN OUT PEFI_DISK_IO2_TOKEN Token, IN UINT_PTR BufferSize, IN PVOID Buffer); typedef EFI_STATUS (*PEFI_DISK_FLUSH_EX)(IN PEFI_DISK_IO2_PROTOCOL This, IN OUT PEFI_DISK_IO2_TOKEN Token); typedef EFI_STATUS (*PEFI_VOLUME_OPEN)(IN PEFI_SIMPLE_FILE_SYSTEM_PROTOCOL This, OUT PEFI_FILE_HANDLE *Root); typedef EFI_STATUS (*PEFI_FILE_OPEN)(IN PEFI_FILE_HANDLE File, OUT PEFI_FILE_HANDLE *NewHandle, IN PWCHAR FileName, IN UINT64 OpenMode, IN UINT64 Attributes); typedef EFI_STATUS (*PEFI_FILE_CLOSE)(IN PEFI_FILE_HANDLE File); typedef EFI_STATUS (*PEFI_FILE_DELETE)(IN PEFI_FILE_HANDLE File); typedef EFI_STATUS (*PEFI_FILE_READ)(IN PEFI_FILE_HANDLE File, IN OUT PUINT_PTR BufferSize, OUT PVOID Buffer); typedef EFI_STATUS (*PEFI_FILE_WRITE)(IN PEFI_FILE_HANDLE File, IN OUT PUINT_PTR BufferSize, IN PVOID Buffer); typedef EFI_STATUS (*PEFI_FILE_SET_POSITION)(IN PEFI_FILE_HANDLE File, IN UINT64 Position); typedef EFI_STATUS (*PEFI_FILE_GET_POSITION)(IN PEFI_FILE_HANDLE File, OUT PUINT64 Position); typedef EFI_STATUS (*PEFI_FILE_GET_INFO)(IN PEFI_FILE_HANDLE File, IN PEFI_GUID InformationType, IN OUT PUINT_PTR BufferSize, OUT PVOID Buffer); typedef EFI_STATUS (*PEFI_FILE_SET_INFO)(IN PEFI_FILE_HANDLE File, IN PEFI_GUID InformationType, IN UINT_PTR BufferSize, IN PVOID Buffer); typedef EFI_STATUS (*PEFI_FILE_FLUSH)(IN PEFI_FILE_HANDLE File); typedef EFI_STATUS (*PEFI_FILE_OPEN_EX)(IN PEFI_FILE_HANDLE File, OUT PEFI_FILE_HANDLE *NewHandle, IN PWCHAR FileName, IN UINT64 OpenMode, IN UINT64 Attributes, IN OUT PEFI_FILE_IO_TOKEN Token); typedef EFI_STATUS (*PEFI_FILE_READ_EX)(IN PEFI_FILE_HANDLE File, IN OUT PEFI_FILE_IO_TOKEN Token); typedef EFI_STATUS (*PEFI_FILE_WRITE_EX)(IN PEFI_FILE_HANDLE File, IN OUT PEFI_FILE_IO_TOKEN Token); typedef EFI_STATUS (*PEFI_FILE_FLUSH_EX)(IN PEFI_FILE_HANDLE File, IN OUT PEFI_FILE_IO_TOKEN Token); typedef EFI_STATUS (*PEFI_LOAD_FILE)(IN PEFI_LOAD_FILE_PROTOCOL This, IN PEFI_DEVICE_PATH_PROTOCOL FilePath, IN UCHAR BootPolicy, IN OUT PUINT_PTR BufferSize, IN PVOID Buffer); typedef EFI_STATUS (*PEFI_DEVICE_IO)(IN PEFI_DEVICE_IO_PROTOCOL This, IN EFI_IO_WIDTH Width, IN UINT64 Address, IN UINT_PTR Count, IN OUT PVOID Buffer); typedef EFI_STATUS (*PEFI_PCIDEV_DEVICE_PATH)(IN PEFI_DEVICE_IO_PROTOCOL This, IN UINT64 Address, IN OUT PEFI_DEVICE_PATH_PROTOCOL *PciDevicePath); typedef EFI_STATUS (*PEFI_IO_MAP)(IN PEFI_DEVICE_IO_PROTOCOL This, IN EFI_IO_OPERATION_TYPE Operation, IN PEFI_PHYSICAL_ADDRESS HostAddress, IN OUT PUINT_PTR NumberOfBytes, OUT PEFI_PHYSICAL_ADDRESS DeviceAddress, OUT PVOID *Mapping); typedef EFI_STATUS (*PEFI_IO_UNMAP)(IN PEFI_DEVICE_IO_PROTOCOL This, IN PVOID Mapping); typedef EFI_STATUS (*PEFI_IO_ALLOCATE_BUFFER)(IN PEFI_DEVICE_IO_PROTOCOL This, IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINT_PTR Pages, IN OUT PEFI_PHYSICAL_ADDRESS HostAddress); typedef EFI_STATUS (*PEFI_IO_FLUSH)(IN PEFI_DEVICE_IO_PROTOCOL This); typedef EFI_STATUS (*PEFI_IO_FREE_BUFFER)(IN PEFI_DEVICE_IO_PROTOCOL This, IN UINT_PTR Pages, IN EFI_PHYSICAL_ADDRESS HostAddress); typedef INT_PTR (*PEFI_UNICODE_STRICOLL)(IN PEFI_UNICODE_COLLATION_PROTOCOL This, IN PUINT16 s1, IN PUINT16 s2); typedef UCHAR (*PEFI_UNICODE_METAIMATCH)(IN PEFI_UNICODE_COLLATION_PROTOCOL This, IN PUINT16 String, IN PUINT16 Pattern); typedef VOID (*PEFI_UNICODE_STRLWR)(IN PEFI_UNICODE_COLLATION_PROTOCOL This, IN OUT PUINT16 Str); typedef VOID (*PEFI_UNICODE_STRUPR)(IN PEFI_UNICODE_COLLATION_PROTOCOL This, IN OUT PUINT16 Str); typedef VOID (*PEFI_UNICODE_FATTOSTR)(IN PEFI_UNICODE_COLLATION_PROTOCOL This, IN UINT_PTR FatSize, IN PUINT8 Fat, OUT PUINT16 String); typedef UCHAR (*PEFI_UNICODE_STRTOFAT)(IN PEFI_UNICODE_COLLATION_PROTOCOL This, IN PUINT16 String, IN UINT_PTR FatSize, OUT PUINT8 Fat); typedef EFI_STATUS (*PEFI_HASH_GET_HASH_SIZE)(IN CONST PEFI_HASH_PROTOCOL This, IN CONST PEFI_GUID HashAlgorithm, OUT PUINT_PTR HashSize); typedef EFI_STATUS (*PEFI_HASH_HASH)(IN CONST PEFI_HASH_PROTOCOL This, IN CONST PEFI_GUID HashAlgorithm, IN UCHAR Extend, IN CONST PUINT8 Message, IN UINT64 MessageSize, IN OUT PEFI_HASH_OUTPUT Hash); typedef EFI_STATUS (*PEFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE)(IN PEFI_GRAPHICS_OUTPUT_PROTOCOL This, IN UINT32 ModeNumber, OUT PUINT_PTR SizeOfInfo, OUT PEFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info); typedef EFI_STATUS (*PEFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE)(IN PEFI_GRAPHICS_OUTPUT_PROTOCOL This, IN UINT32 ModeNumber); typedef EFI_STATUS (*PEFI_GRAPHICS_OUTPUT_PROTOCOL_BLT)(IN PEFI_GRAPHICS_OUTPUT_PROTOCOL This, IN PEFI_GRAPHICS_OUTPUT_BLT_PIXEL BltBuffer, IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, IN UINT_PTR SourceX, IN UINT_PTR SourceY, IN UINT_PTR DestinationX, IN UINT_PTR DestinationY, IN UINT_PTR Width, IN UINT_PTR Height, IN UINT_PTR Delta); typedef EFI_STATUS (*PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL_GET_MODE)(IN PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL This, OUT PUINT32 HorizontalResolution, OUT PUINT32 VerticalResolution, OUT PUINT32 ColorDepth, OUT PUINT32 RefreshRate); typedef EFI_STATUS (*PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL_SET_MODE)(IN PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL This, IN UINT32 HorizontalResolution, IN UINT32 VerticalResolution, IN UINT32 ColorDepth, IN UINT32 RefreshRate); typedef EFI_STATUS (*PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL_BLT)(IN PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL This, IN PEFI_UNIVERSAL_GRAPHICS_BLT_PIXEL BltBuffer, IN EFI_UNIVERSA_GRAPHICS_BLT_OPERATION BltOperation, IN UINT_PTR SourceX, IN UINT_PTR SourceY, IN UINT_PTR DestinationX, IN UINT_PTR DestinationY, IN UINT_PTR Width, IN UINT_PTR Height, IN UINT_PTR Delta); typedef EFI_STATUS (*PEFI_EDID_OVERRIDE_PROTOCOL_GET_EDID)(IN PEFI_EDID_OVERRIDE_PROTOCOL This, IN PEFI_HANDLE ChildHandle, OUT PUINT32 Attributes, IN OUT PUINT_PTR EdidSize, IN OUT PUINT8 *Edid); typedef EFI_STATUS (*PEFI_LEGACY_BIOS_BOOT)(IN PEFI_LEGACY_BIOS_PROTOCOL This, IN PEFI_BBS_BBS_DEVICE_PATH BootOption, IN UINT32 LoadOptionsSize, IN PVOID LoadOptions); typedef EFI_STATUS (*PEFI_LEGACY_BIOS_BOOT_UNCONVENTIONAL_DEVICE)(IN PEFI_LEGACY_BIOS_PROTOCOL This, IN EFI_UDC_ATTRIBUTES Attributes, IN UINT_PTR BbsEntry, IN PVOID BeerData, IN PVOID ServiceAreaData); typedef EFI_STATUS (*PEFI_LEGACY_BIOS_CHECK_ROM)(IN PEFI_LEGACY_BIOS_PROTOCOL This, IN EFI_HANDLE PciHandle, OUT PVOID *RomImage, OUT PUINT_PTR RomSize, OUT PUINT_PTR Flags); typedef EFI_STATUS (*PEFI_LEGACY_BIOS_COPY_LEGACY_REGION)(IN PEFI_LEGACY_BIOS_PROTOCOL This, IN UINT_PTR LegacyMemorySize, IN VOID *LegacyMemoryAddress, IN VOID *LegacyMemorySourceAddress); typedef BOOLEAN (*PEFI_LEGACY_BIOS_FARCALL86)(IN PEFI_LEGACY_BIOS_PROTOCOL This, IN UINT16 Segment, IN UINT16 Offset, IN PEFI_IA32_REGISTER_SET Regs, IN PVOID Stack, IN UINT_PTR StackSize); typedef EFI_STATUS (*PEFI_LEGACY_BIOS_GET_BBS_INFO)(IN PEFI_LEGACY_BIOS_PROTOCOL This, OUT PUINT16 HddCount, OUT PEFI_HDD_INFO *HddInfo, OUT PUINT16 BbsCount, IN OUT PEFI_BBS_TABLE *BbsTable); typedef EFI_STATUS (*PEFI_LEGACY_BIOS_GET_LEGACY_REGION)(IN PEFI_LEGACY_BIOS_PROTOCOL This, IN UINT_PTR LegacyMemorySize, IN UINT_PTR Region, IN UINT_PTR Alignment, OUT PVOID *LegacyMemoryAddress); typedef EFI_STATUS (*PEFI_LEGACY_BIOS_INSTALL_ROM)(IN PEFI_LEGACY_BIOS_PROTOCOL This, IN EFI_HANDLE PciHandle, IN PVOID *RomImage, OUT PUINT_PTR Flags, OUT PUINT8 DiskStart, OUT PUINT8 DiskEnd, OUT PVOID *RomShadowAddress, OUT PUINT32 ShadowedRomSize); typedef BOOLEAN (*PEFI_LEGACY_BIOS_INT86)(IN PEFI_LEGACY_BIOS_PROTOCOL This, IN UINT8 BiosInt, IN OUT PEFI_IA32_REGISTER_SET Regs); typedef EFI_STATUS (*PEFI_LEGACY_BIOS_PREPARE_TO_BOOT_EFI)(IN PEFI_LEGACY_BIOS_PROTOCOL This, OUT PUINT16 BbsCount, OUT PEFI_BBS_TABLE *BbsTable); typedef EFI_STATUS (*PEFI_LEGACY_BIOS_SHADOW_ALL_LEGACY_OPROMS)(IN PEFI_LEGACY_BIOS_PROTOCOL This); typedef EFI_STATUS (*PEFI_LEGACY_BIOS_UPDATE_KEYBOARD_LED_STATUS)(IN PEFI_LEGACY_BIOS_PROTOCOL This, IN UINT8 Leds); typedef EFI_STATUS (*PEFI_SERVICE_BINDING_CREATE_CHILD)(IN PEFI_SERVICE_BINDING This, IN PEFI_HANDLE ChildHandle); typedef EFI_STATUS (*PEFI_SERVICE_BINDING_DESTROY_CHILD)(IN PEFI_SERVICE_BINDING This, IN EFI_HANDLE ChildHandle); typedef EFI_STATUS (*PEFI_DRIVER_BINDING_PROTOCOL_SUPPORTED)(IN PEFI_DRIVER_BINDING_PROTOCOL This, IN EFI_HANDLE ControllerHandle, IN PEFI_DEVICE_PATH_PROTOCOL RemainingDevicePath); typedef EFI_STATUS (*PEFI_DRIVER_BINDING_PROTOCOL_START)(IN PEFI_DRIVER_BINDING_PROTOCOL This, IN EFI_HANDLE ControllerHandle, IN PEFI_DEVICE_PATH_PROTOCOL RemainingDevicePath); typedef EFI_STATUS (*PEFI_DRIVER_BINDING_PROTOCOL_STOP)(IN PEFI_DRIVER_BINDING_PROTOCOL This, IN EFI_HANDLE ControllerHandle, IN UINT_PTR NumberOfChildren, IN PEFI_HANDLE ChildHandleBuffer); typedef EFI_STATUS (*PEFI_COMPONENT_NAME_GET_DRIVER_NAME)(IN PEFI_COMPONENT_NAME_PROTOCOL This, IN PUINT8 Language, OUT PWCHAR *DriverName); typedef EFI_STATUS (*PEFI_COMPONENT_NAME_GET_CONTROLLER_NAME)(IN PEFI_COMPONENT_NAME_PROTOCOL This, IN EFI_HANDLE ControllerHandle, IN EFI_HANDLE ChildHandle, IN PUINT8 Language, OUT PWCHAR *ControllerName); typedef EFI_STATUS (*PEFI_COMPONENT_NAME2_GET_DRIVER_NAME)(IN PEFI_COMPONENT_NAME2_PROTOCOL This, IN PUINT8 Language, OUT PWCHAR *DriverName); typedef EFI_STATUS (*PEFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)(IN PEFI_COMPONENT_NAME2_PROTOCOL This, IN EFI_HANDLE ControllerHandle, IN EFI_HANDLE ChildHandle, IN PUINT8 Language, OUT PWCHAR *ControllerName); typedef EFI_STATUS (*PEFI_RNG_GET_INFO)(IN PEFI_RNG_PROTOCOL This, IN OUT PUINT_PTR RNGAlgorithmListSize, OUT PEFI_GUID RNGAlgorithmList); typedef EFI_STATUS (*PEFI_RNG_GET_RNG)(IN PEFI_RNG_PROTOCOL This, IN PEFI_GUID RNGAlgorithm, IN UINT_PTR RNGValueLength, OUT PUINT8 RNGValue); typedef EFI_STATUS (*PEFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER)(IN PEFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL This, IN EFI_HANDLE ControllerHandle, IN OUT PEFI_HANDLE DriverImageHandle); typedef EFI_STATUS (*PEFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER_PATH)(IN PEFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL This, IN EFI_HANDLE ControllerHandle, IN OUT PEFI_DEVICE_PATH_PROTOCOL *DriverImagePath); typedef EFI_STATUS (*PEFI_PLATFORM_DRIVER_OVERRIDE_DRIVER_LOADED)(IN PEFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL This, IN EFI_HANDLE ControllerHandle, IN PEFI_DEVICE_PATH_PROTOCOL DriverImagePath, IN EFI_HANDLE DriverImageHandle); typedef EFI_STATUS (*PEFI_BUS_SPECIFIC_DRIVER_OVERRIDE_GET_DRIVER)(IN PEFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL This, IN OUT PEFI_HANDLE DriverImageHandle); typedef UINT32 (*PEFI_DRIVER_FAMILY_OVERRIDE_GET_VERSION)(IN PEFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL This); typedef EFI_STATUS (*PEFI_EBC_CREATE_THUNK)(IN PEFI_EBC_PROTOCOL This, IN EFI_HANDLE ImageHandle, IN PVOID EbcEntryPoint, OUT PVOID *Thunk); typedef EFI_STATUS (*PEFI_EBC_UNLOAD_IMAGE)(IN PEFI_EBC_PROTOCOL This, IN EFI_HANDLE ImageHandle); typedef EFI_STATUS (*PEFI_EBC_ICACHE_FLUSH)(IN EFI_PHYSICAL_ADDRESS Start, IN UINT64 Length); typedef EFI_STATUS (*PEFI_EBC_REGISTER_ICACHE_FLUSH)(IN PEFI_EBC_PROTOCOL This, IN PEFI_EBC_ICACHE_FLUSH Flush); typedef EFI_STATUS (*PEFI_EBC_GET_VERSION)(IN PEFI_EBC_PROTOCOL This, IN OUT PUINT64 Version); typedef EFI_STATUS (*PEFI_UART_RESET)(IN PEFI_UART_IO_PROTOCOL This); typedef EFI_STATUS (*PEFI_UART_SET_ATTRIBUTES)(IN PEFI_UART_IO_PROTOCOL This, IN UINT64 BaudRate, IN UINT32 ReceiveFifoDepth, IN UINT32 Timeout, IN EFI_UART_PARITY_TYPE Parity, IN UINT8 DataBits, IN EFI_UART_STOP_BITS_TYPE StopBits); typedef EFI_STATUS (*PEFI_UART_SET_CONTROL_BITS)(IN PEFI_UART_IO_PROTOCOL This, IN UINT32 Control); typedef EFI_STATUS (*PEFI_UART_GET_CONTROL_BITS)(IN PEFI_UART_IO_PROTOCOL This, OUT PUINT32 Control); typedef EFI_STATUS (*PEFI_UART_WRITE)(IN PEFI_UART_IO_PROTOCOL This, IN OUT PUINT_PTR BufferSize, IN PVOID Buffer); typedef EFI_STATUS (*PEFI_UART_READ)(IN PEFI_UART_IO_PROTOCOL This, IN OUT PUINT_PTR BufferSize, OUT PVOID Buffer); typedef EFI_STATUS (*PEFI_SIMPLE_NETWORK_START)(IN PEFI_SIMPLE_NETWORK_PROTOCOL This); typedef EFI_STATUS (*PEFI_SIMPLE_NETWORK_STOP)(IN PEFI_SIMPLE_NETWORK_PROTOCOL This); typedef EFI_STATUS (*PEFI_SIMPLE_NETWORK_INITIALIZE)(IN PEFI_SIMPLE_NETWORK_PROTOCOL This, IN UINT_PTR ExtraRxBufferSize, IN UINT_PTR ExtraTxBufferSize); typedef EFI_STATUS (*PEFI_SIMPLE_NETWORK_RESET)(IN PEFI_SIMPLE_NETWORK_PROTOCOL This, IN UCHAR ExtendedVerification); typedef EFI_STATUS (*PEFI_SIMPLE_NETWORK_SHUTDOWN)(IN PEFI_SIMPLE_NETWORK_PROTOCOL This); typedef EFI_STATUS (*PEFI_SIMPLE_NETWORK_RECEIVE_FILTERS)(IN PEFI_SIMPLE_NETWORK_PROTOCOL This, IN UINT32 Enable, IN UINT32 Disable, IN UCHAR ResetMCastFilter, IN UINT_PTR MCastFilterCnt, IN PEFI_MAC_ADDRESS MCastFilter); typedef EFI_STATUS (*PEFI_SIMPLE_NETWORK_STATION_ADDRESS)(IN PEFI_SIMPLE_NETWORK_PROTOCOL This, IN UCHAR Reset, IN PEFI_MAC_ADDRESS New); typedef EFI_STATUS (*PEFI_SIMPLE_NETWORK_STATISTICS)(IN PEFI_SIMPLE_NETWORK_PROTOCOL This, IN UCHAR Reset, IN OUT PUINT_PTR StatisticsSize, OUT PEFI_NETWORK_STATISTICS StatisticsTable); typedef EFI_STATUS (*PEFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC)(IN PEFI_SIMPLE_NETWORK_PROTOCOL This, IN UCHAR IPv6, IN PEFI_IP_ADDRESS IP, OUT PEFI_MAC_ADDRESS MAC); typedef EFI_STATUS (*PEFI_SIMPLE_NETWORK_NVDATA)(IN PEFI_SIMPLE_NETWORK_PROTOCOL This, IN UCHAR ReadWrite, IN UINT_PTR Offset, IN UINT_PTR BufferSize, IN OUT PVOID Buffer); typedef EFI_STATUS (*PEFI_SIMPLE_NETWORK_GET_STATUS)(IN PEFI_SIMPLE_NETWORK_PROTOCOL This, OUT PUINT32 InterruptStatus, OUT PVOID *TxBuf); typedef EFI_STATUS (*PEFI_SIMPLE_NETWORK_TRANSMIT)(IN PEFI_SIMPLE_NETWORK_PROTOCOL This, IN UINT_PTR HeaderSize, IN UINT_PTR BufferSize, IN PVOID Buffer, IN PEFI_MAC_ADDRESS SrcAddr, IN PEFI_MAC_ADDRESS DestAddr, IN PUINT16 Protocol); typedef EFI_STATUS (*PEFI_SIMPLE_NETWORK_RECEIVE)(IN PEFI_SIMPLE_NETWORK_PROTOCOL This, OUT PUINT_PTR HeaderSize, IN OUT PUINT_PTR BufferSize, OUT PVOID Buffer, OUT PEFI_MAC_ADDRESS SrcAddr, OUT PEFI_MAC_ADDRESS DestAddr, OUT PUINT16 Protocol); typedef EFI_STATUS (*PEFI_PXE_BASE_CODE_START)(IN PEFI_PXE_BASE_CODE_PROTOCOL This, IN UCHAR UseIpv6); typedef EFI_STATUS (*PEFI_PXE_BASE_CODE_STOP)(IN PEFI_PXE_BASE_CODE_PROTOCOL This); typedef EFI_STATUS (*PEFI_PXE_BASE_CODE_DHCP)(IN PEFI_PXE_BASE_CODE_PROTOCOL This, IN UCHAR SortOffers); typedef EFI_STATUS (*PEFI_PXE_BASE_CODE_DISCOVER)(IN PEFI_PXE_BASE_CODE_PROTOCOL This, IN UINT16 Type, IN PUINT16 Layer, IN UCHAR UseBis, IN OUT PEFI_PXE_BASE_CODE_DISCOVER_INFO Info); typedef EFI_STATUS (*PEFI_PXE_BASE_CODE_MTFTP)(IN PEFI_PXE_BASE_CODE_PROTOCOL This, IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation, IN OUT PVOID *BufferPtr, IN UCHAR Overwrite, IN OUT PUINT64 BufferSize, IN PUINT_PTR BlockSize, IN PEFI_IP_ADDRESS ServerIp, IN PWCHAR Filename, IN PEFI_PXE_BASE_CODE_MTFTP_INFO Info, IN UCHAR DontUseBuffer); typedef EFI_STATUS (*PEFI_PXE_BASE_CODE_UDP_WRITE)(IN PEFI_PXE_BASE_CODE_PROTOCOL This, IN UINT16 OpFlags, IN PEFI_IP_ADDRESS DestIp, IN PUINT16 DestPort, IN PEFI_IP_ADDRESS GatewayIp, IN PEFI_IP_ADDRESS SrcIp, IN OUT PUINT16 SrcPort, IN PUINT_PTR HeaderSize, IN PVOID HeaderPtr, IN PUINT_PTR BufferSize, IN PVOID BufferPtr); typedef EFI_STATUS (*PEFI_PXE_BASE_CODE_UDP_READ)(IN PEFI_PXE_BASE_CODE_PROTOCOL This, IN UINT16 OpFlags, IN OUT PEFI_IP_ADDRESS DestIp, IN OUT PUINT16 DestPort, IN OUT PEFI_IP_ADDRESS SrcIp, IN OUT PUINT16 SrcPort, IN PUINT_PTR HeaderSize, IN PVOID HeaderPtr, IN OUT PUINT_PTR BufferSize, IN PVOID BufferPtr); typedef EFI_STATUS (*PEFI_PXE_BASE_CODE_SET_IP_FILTER)(IN PEFI_PXE_BASE_CODE_PROTOCOL This, IN PEFI_PXE_BASE_CODE_IP_FILTER NewFilter); typedef EFI_STATUS (*PEFI_PXE_BASE_CODE_ARP)(IN PEFI_PXE_BASE_CODE_PROTOCOL This, IN PEFI_IP_ADDRESS IpAddr, IN PEFI_MAC_ADDRESS MacAddr); typedef EFI_STATUS (*PEFI_PXE_BASE_CODE_SET_PARAMETERS)(IN PEFI_PXE_BASE_CODE_PROTOCOL This, IN PUCHAR NewAutoArp, IN PUCHAR NewSendGUID, IN PUINT8 NewTTL, IN PUINT8 NewToS, IN PUCHAR NewMakeCallback); typedef EFI_STATUS (*PEFI_PXE_BASE_CODE_SET_STATION_IP)(IN PEFI_PXE_BASE_CODE_PROTOCOL This, IN PEFI_IP_ADDRESS NewStationIp, IN PEFI_IP_ADDRESS NewSubnetMask); typedef EFI_STATUS (*PEFI_PXE_BASE_CODE_SET_PACKETS)(IN PEFI_PXE_BASE_CODE_PROTOCOL This, PUCHAR NewDhcpDiscoverValid, PUCHAR NewDhcpAckReceived, PUCHAR NewProxyOfferReceived, PUCHAR NewPxeDiscoverValid, PUCHAR NewPxeReplyReceived, PUCHAR NewPxeBisReplyReceived, IN PEFI_PXE_BASE_CODE_PACKET NewDhcpDiscover, IN PEFI_PXE_BASE_CODE_PACKET NewDhcpAck, IN PEFI_PXE_BASE_CODE_PACKET NewProxyOffer, IN PEFI_PXE_BASE_CODE_PACKET NewPxeDiscover, IN PEFI_PXE_BASE_CODE_PACKET NewPxeReply, IN PEFI_PXE_BASE_CODE_PACKET NewPxeBisReply); typedef EFI_PXE_BASE_CODE_CALLBACK_STATUS (*PEFI_PXE_CALLBACK)(IN PEFI_PXE_BASE_CODE_CALLBACK_PROTOCOL This, IN EFI_PXE_BASE_CODE_FUNCTION Function, IN UCHAR Received, IN UINT32 PacketLen, IN PEFI_PXE_BASE_CODE_PACKET Packet); typedef VOID (*PEFI_AP_PROCEDURE)(IN OUT PVOID Buffer); typedef EFI_STATUS (*PEFI_FRAMEWORK_MP_SERVICES_GET_GENERAL_MP_INFO)(IN PEFI_FRAMEWORK_MP_SERVICES_PROTOCOL This, OUT PUINT_PTR NumberOfCPUs, OUT PUINT_PTR MaximumNumberOfCPUs, OUT PUINT_PTR NumberOfEnabledCPUs, OUT PUINT_PTR RendezvousIntNumber, OUT PUINT_PTR RendezvousProcLength); typedef EFI_STATUS (*PEFI_FRAMEWORK_MP_SERVICES_GET_PROCESSOR_CONTEXT)(IN PEFI_FRAMEWORK_MP_SERVICES_PROTOCOL This, IN UINT_PTR ProcessorNumber, IN OUT PUINT_PTR BufferLength, IN OUT PEFI_FRAMEWORK_MP_PROCESSOR_CONTEXT ProcessorContextBuffer); typedef EFI_STATUS (*PEFI_FRAMEWORK_MP_SERVICES_STARTUP_ALL_APS)(IN PEFI_FRAMEWORK_MP_SERVICES_PROTOCOL This, IN PEFI_AP_PROCEDURE Procedure, IN BOOLEAN SingleThread, IN EFI_EVENT WaitEvent, IN UINT_PTR TimeoutInMicroSecs, IN OUT PVOID ProcArguments, OUT PUINT_PTR FailedCPUList); typedef EFI_STATUS (*PEFI_FRAMEWORK_MP_SERVICES_STARTUP_THIS_AP)(IN PEFI_FRAMEWORK_MP_SERVICES_PROTOCOL This, IN PEFI_AP_PROCEDURE Procedure, IN UINT_PTR ProcessorNumber, IN EFI_EVENT WaitEvent, IN UINT_PTR TimeoutInMicroSecs, IN OUT PVOID ProcArguments); typedef EFI_STATUS (*PEFI_FRAMEWORK_MP_SERVICES_SWITCH_BSP)(IN PEFI_FRAMEWORK_MP_SERVICES_PROTOCOL This, IN UINT_PTR ProcessorNumber, IN BOOLEAN EnableOldBSP); typedef EFI_STATUS (*PEFI_FRAMEWORK_MP_SERVICES_SEND_IPI)(IN PEFI_FRAMEWORK_MP_SERVICES_PROTOCOL This, IN UINT_PTR ProcessorNumber, IN UINT_PTR VectorNumber, IN UINT_PTR DeliveryMode); typedef EFI_STATUS (*PEFI_FRAMEWORK_MP_SERVICES_ENABLEDISABLEAP)(IN PEFI_FRAMEWORK_MP_SERVICES_PROTOCOL This, IN UINT_PTR ProcessorNumber, IN BOOLEAN NewAPState, IN PEFI_FRAMEWORK_MP_HEALTH HealthState); typedef EFI_STATUS (*PEFI_FRAMEWORK_MP_SERVICES_WHOAMI)(IN PEFI_FRAMEWORK_MP_SERVICES_PROTOCOL This, OUT PUINT_PTR ProcessorNumber); typedef EFI_STATUS (*PEFI_MP_SERVICES_ENABLEDISABLEAP)(IN PEFI_MP_SERVICES_PROTOCOL This, IN UINT_PTR ProcessorNumber, IN BOOLEAN EnableAP, IN PUINT32 HealthFlag); typedef EFI_STATUS (*PEFI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS)(IN PEFI_MP_SERVICES_PROTOCOL This, OUT PUINT_PTR NumberOfProcessors, OUT PUINT_PTR NumberOfEnabledProcessors); typedef EFI_STATUS (*PEFI_MP_SERVICES_GET_PROCESSOR_INFO)(IN PEFI_MP_SERVICES_PROTOCOL This, IN UINT_PTR ProcessorNumber, OUT PEFI_PROCESSOR_INFORMATION ProcessorInfoBuffer); typedef EFI_STATUS (*PEFI_MP_SERVICES_STARTUP_ALL_APS)(IN PEFI_MP_SERVICES_PROTOCOL This, IN PEFI_AP_PROCEDURE Procedure, IN BOOLEAN SingleThread, IN EFI_EVENT WaitEvent, IN UINT_PTR TimeoutInMicroSeconds, IN PVOID ProcedureArgument, OUT PUINT_PTR *FailedCpuList); typedef EFI_STATUS (*PEFI_MP_SERVICES_STARTUP_THIS_AP)(IN PEFI_MP_SERVICES_PROTOCOL This, IN PEFI_AP_PROCEDURE Procedure, IN UINT_PTR ProcessorNumber, IN EFI_EVENT WaitEvent, IN UINT_PTR TimeoutInMicroseconds, IN PVOID ProcedureArgument, OUT PBOOLEAN Finished); typedef EFI_STATUS (*PEFI_MP_SERVICES_SWITCH_BSP)(IN PEFI_MP_SERVICES_PROTOCOL This, IN UINT_PTR ProcessorNumber, IN BOOLEAN EnableOldBSP); typedef EFI_STATUS (*PEFI_MP_SERVICES_WHOAMI)(IN PEFI_MP_SERVICES_PROTOCOL This, OUT PUINT_PTR ProcessorNumber); /* 128-bit buffer containing a unique identifier value */ typedef struct _EFI_GUID { UINT32 Data1; UINT16 Data2; UINT16 Data3; UINT8 Data4[8]; } EFI_GUID, *PEFI_GUID; /* EFI Capsule Header */ typedef struct _EFI_CAPSULE_HEADER { EFI_GUID CapsuleGuid; UINT32 HeaderSize; UINT32 Flags; UINT32 CapsuleImageSize; } EFI_CAPSULE_HEADER, *PEFI_CAPSULE_HEADER; /* EFI Capsule Block Descriptor */ typedef struct _EFI_CAPSULE_BLOCK_DESCRIPTOR { UINT64 Length; union { EFI_PHYSICAL_ADDRESS DataBlock; EFI_PHYSICAL_ADDRESS ContinuationPointer; } Union; } EFI_CAPSULE_BLOCK_DESCRIPTOR, *PEFI_CAPSULE_BLOCK_DESCRIPTOR; /* Definition of an EFI memory descriptor */ typedef struct _EFI_MEMORY_DESCRIPTOR { UINT32 Type; UINT32 Pad; EFI_PHYSICAL_ADDRESS PhysicalStart; EFI_VIRTUAL_ADDRESS VirtualStart; UINT64 NumberOfPages; UINT64 Attribute; } EFI_MEMORY_DESCRIPTOR, *PEFI_MEMORY_DESCRIPTOR; /* Definition of an EFI memory map */ typedef struct _EFI_MEMORY_MAP { PEFI_MEMORY_DESCRIPTOR Map; UINT_PTR MapSize; UINT_PTR MapKey; UINT_PTR DescriptorSize; UINT32 DescriptorVersion; } EFI_MEMORY_MAP, *PEFI_MEMORY_MAP; /* Data structure that precedes all of the standard EFI table types */ typedef struct _EFI_TABLE_HEADER { UINT64 Signature; UINT32 Revision; UINT32 HeaderSize; UINT32 CRC32; UINT32 Reserved; } EFI_TABLE_HEADER, *PEFI_TABLE_HEADER; /* EFI Time Abstraction */ typedef struct _EFI_TIME { UINT16 Year; UINT8 Month; UINT8 Day; UINT8 Hour; UINT8 Minute; UINT8 Second; UINT8 Pad1; UINT32 Nanosecond; INT16 TimeZone; UINT8 Daylight; UINT8 PAD2; } EFI_TIME, *PEFI_TIME; /* Provides the capabilities of the RTC device as exposed through the EFI interfaces */ typedef struct _EFI_TIME_CAPABILITIES { UINT32 Resolution; UINT32 Accuracy; BOOLEAN SetsToZero; } EFI_TIME_CAPABILITIES, *PEFI_TIME_CAPABILITIES; /* EFI Open Protocol Information Entry */ typedef struct _EFI_OPEN_PROTOCOL_INFORMATION_ENTRY { EFI_HANDLE AgentHandle; EFI_HANDLE ControllerHandle; UINT32 Attributes; UINT32 OpenCount; } EFI_OPEN_PROTOCOL_INFORMATION_ENTRY, *PEFI_OPEN_PROTOCOL_INFORMATION_ENTRY; /* EFI Boot Services Table */ typedef struct _EFI_BOOT_SERVICES { EFI_TABLE_HEADER Hdr; PEFI_RAISE_TPL RaiseTPL; PEFI_RESTORE_TPL RestoreTPL; PEFI_ALLOCATE_PAGES AllocatePages; PEFI_FREE_PAGES FreePages; PEFI_GET_MEMORY_MAP GetMemoryMap; PEFI_ALLOCATE_POOL AllocatePool; PEFI_FREE_POOL FreePool; PEFI_CREATE_EVENT CreateEvent; PEFI_SET_TIMER SetTimer; PEFI_WAIT_FOR_EVENT WaitForEvent; PEFI_SIGNAL_EVENT SignalEvent; PEFI_CLOSE_EVENT CloseEvent; PEFI_CHECK_EVENT CheckEvent; PEFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface; PEFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface; PEFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface; PEFI_HANDLE_PROTOCOL HandleProtocol; PVOID Reserved; PEFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify; PEFI_LOCATE_HANDLE LocateHandle; PEFI_LOCATE_DEVICE_PATH LocateDevicePath; PEFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable; PEFI_IMAGE_LOAD LoadImage; PEFI_IMAGE_START StartImage; PEFI_EXIT Exit; PEFI_IMAGE_UNLOAD UnloadImage; PEFI_EXIT_BOOT_SERVICES ExitBootServices; PEFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; PEFI_STALL Stall; PEFI_SET_WATCHDOG_TIMER SetWatchdogTimer; PEFI_CONNECT_CONTROLLER ConnectController; PEFI_DISCONNECT_CONTROLLER DisconnectController; PEFI_OPEN_PROTOCOL OpenProtocol; PEFI_CLOSE_PROTOCOL CloseProtocol; PEFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation; PEFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle; PEFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer; PEFI_LOCATE_PROTOCOL LocateProtocol; PEFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces; PEFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces; PEFI_CALCULATE_CRC32 CalculateCrc32; PEFI_COPY_MEM CopyMem; PEFI_SET_MEM SetMem; PEFI_CREATE_EVENT_EX CreateEventEx; } EFI_BOOT_SERVICES, *PEFI_BOOT_SERVICES; /* EFI Runtime Services Table */ typedef struct _EFI_RUNTIME_SERVICES { EFI_TABLE_HEADER Hdr; PEFI_GET_TIME GetTime; PEFI_SET_TIME SetTime; PEFI_GET_WAKEUP_TIME GetWakeupTime; PEFI_SET_WAKEUP_TIME SetWakeupTime; PEFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap; PEFI_CONVERT_POINTER ConvertPointer; PEFI_GET_VARIABLE GetVariable; PEFI_GET_NEXT_VARIABLE_NAME GetNextVariableName; PEFI_SET_VARIABLE SetVariable; PEFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount; PEFI_RESET_SYSTEM ResetSystem; PEFI_UPDATE_CAPSULE UpdateCapsule; PEFI_QUERY_CAPSULE_CAPABILITIES QueryCapsuleCapabilities; PEFI_QUERY_VARIABLE_INFO QueryVariableInfo; } EFI_RUNTIME_SERVICES, *PEFI_RUNTIME_SERVICES; /* Contains a set of GUID/pointer pairs comprised of the ConfigurationTable field in the EFI System Table */ typedef struct _EFI_CONFIGURATION_TABLE { EFI_GUID VendorGuid; PVOID VendorTable; } EFI_CONFIGURATION_TABLE, *PEFI_CONFIGURATION_TABLE; /* Simple Text Input protocol from the UEFI 2.0 specification */ typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL { PEFI_INPUT_RESET Reset; PEFI_INPUT_READ_KEY ReadKeyStroke; EFI_EVENT WaitForKey; } EFI_SIMPLE_TEXT_INPUT_PROTOCOL, *PEFI_SIMPLE_TEXT_INPUT_PROTOCOL; /* Simple Text Output protocol from the UEFI 2.0 specification */ typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { PEFI_TEXT_RESET Reset; PEFI_TEXT_OUTPUT_STRING OutputString; PEFI_TEXT_TEST_STRING TestString; PEFI_TEXT_QUERY_MODE QueryMode; PEFI_TEXT_SET_MODE SetMode; PEFI_TEXT_SET_ATTRIBUTE SetAttribute; PEFI_TEXT_CLEAR_SCREEN ClearScreen; PEFI_TEXT_SET_CURSOR_POSITION SetCursorPosition; PEFI_TEXT_ENABLE_CURSOR EnableCursor; PEFI_SIMPLE_TEXT_OUTPUT_MODE Mode; } EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL, *PEFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; /* Mode Structure pointed to by Simple Text Out protocol */ typedef struct _EFI_SIMPLE_TEXT_OUTPUT_MODE { INT32 MaxMode; INT32 Mode; INT32 Attribute; INT32 CursorColumn; INT32 CursorRow; BOOLEAN CursorVisible; } EFI_SIMPLE_TEXT_OUTPUT_MODE, *PEFI_SIMPLE_TEXT_OUTPUT_MODE; /* The keystroke information for the key that was pressed */ typedef struct _EFI_INPUT_KEY { UINT16 ScanCode; WCHAR UnicodeChar; } EFI_INPUT_KEY, *PEFI_INPUT_KEY; /* EFI Key State information */ typedef struct _EFI_KEY_STATE { UINT32 KeyShiftState; UINT8 KeyToggleState; } EFI_KEY_STATE, *PEFI_KEY_STATE; /* EFI Key Data information */ typedef struct _EFI_KEY_DATA { EFI_INPUT_KEY Key; EFI_KEY_STATE KeyState; } EFI_KEY_DATA, *PEFI_KEY_DATA; /* EFI Simple Text Input Ex protocol */ typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL { PEFI_INPUT_RESET_EX Reset; PEFI_INPUT_READ_KEY_EX ReadKeyStrokeEx; EFI_EVENT WaitForKeyEx; PEFI_SET_STATE SetState; PEFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify; PEFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify; } EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL, *PEFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL; /* EFI System Table */ typedef struct _EFI_SYSTEM_TABLE { EFI_TABLE_HEADER Hdr; PWCHAR FirmwareVendor; UINT32 FirmwareRevision; EFI_HANDLE ConsoleInHandle; PEFI_SIMPLE_TEXT_INPUT_PROTOCOL ConIn; EFI_HANDLE ConsoleOutHandle; PEFI_SIMPLE_TEXT_OUTPUT_PROTOCOL ConOut; EFI_HANDLE StandardErrorHandle; PEFI_SIMPLE_TEXT_OUTPUT_PROTOCOL StdErr; PEFI_RUNTIME_SERVICES RuntimeServices; PEFI_BOOT_SERVICES BootServices; UINT_PTR NumberOfTableEntries; PEFI_CONFIGURATION_TABLE ConfigurationTable; } EFI_SYSTEM_TABLE, *PEFI_SYSTEM_TABLE; /* EFI IPv4 network protocol */ typedef struct _EFI_IPv4_ADDRESS { UINT8 Addr[4]; } EFI_IPv4_ADDRESS, *PEFI_IPv4_ADDRESS; /* EFI IPv6 network protocol */ typedef struct _EFI_IPv6_ADDRESS { UINT8 Addr[16]; } EFI_IPv6_ADDRESS, *PEFI_IPv6_ADDRESS; /* EFI MAC address definition */ typedef struct _EFI_MAC_ADDRESS { UINT8 Addr[32]; } EFI_MAC_ADDRESS, *PEFI_MAC_ADDRESS; /* EFI network interface identifier protocol */ typedef struct _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL { UINT64 Revision; UINT64 ID; UINT64 ImageAddr; UINT32 ImageSize; UINT8 StringId[4]; UINT8 Type; UINT8 MajorVer; UINT8 MinorVer; UCHAR Ipv6Supported; UINT8 IfNum; } EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL, *PEFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE; /* EFI network configuration data structure */ typedef struct _EFI_MANAGED_NETWORK_CONFIG_DATA { UINT32 ReceivedQueueTimeoutValue; UINT32 TransmitQueueTimeoutValue; UINT16 ProtocolTypeFilter; UCHAR EnableUnicastReceive; UCHAR EnableMulticastReceive; UCHAR EnableBroadcastReceive; UCHAR EnablePromiscuousReceive; UCHAR FlushQueuesOnReset; UCHAR EnableReceiveTimestamps; UCHAR DisableBackgroundPolling; } EFI_MANAGED_NETWORK_CONFIG_DATA, *PEFI_MANAGED_NETWORK_CONFIG_DATA; /* Describes the location of the device the handle is for */ typedef struct _EFI_DEVICE_PATH_PROTOCOL { UINT8 Type; UINT8 SubType; UINT8 Length[2]; } EFI_DEVICE_PATH_PROTOCOL, *PEFI_DEVICE_PATH_PROTOCOL; /* PCI device path node */ typedef struct _EFI_PCI_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT8 Function; UINT8 Device; } EFI_PCI_DEVICE_PATH, *PEFI_PCI_DEVICE_PATH; /* PCCARD device path node */ typedef struct _EFI_PCCARD_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT8 FunctionNumber; } EFI_PCCARD_DEVICE_PATH, *PEFI_PCCARD_DEVICE_PATH; /* MemMap device path node */ typedef struct _EFI_MEMMAP_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT32 MemoryType; EFI_PHYSICAL_ADDRESS StartingAddress; EFI_PHYSICAL_ADDRESS EndingAddress; } EFI_MEMMAP_DEVICE_PATH, *PEFI_MEMMAP_DEVICE_PATH; /* Vendor device path node */ typedef struct _EFI_VENDOR_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; EFI_GUID Guid; } EFI_VENDOR_DEVICE_PATH, *PEFI_VENDOR_DEVICE_PATH; /* Unknown Device Vendor device path node */ typedef struct _EFI_UKNOWN_DEVICE_VENDOR_DEVICE_PATH { EFI_VENDOR_DEVICE_PATH DevicePath; UINT8 LegacyDriveLetter; } EFI_UNKNOWN_DEVICE_VENDOR_DEVICE_PATH, *PEFI_UNKNOWN_DEVICE_VENDOR_DEVICE_PATH; /* Controller device path node */ typedef struct _EFI_CONTROLLER_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT32 Controller; } EFI_CONTROLLER_DEVICE_PATH, *PEFI_CONTROLLER_DEVICE_PATH; /* ACPI address space descriptor */ typedef struct _EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR { UCHAR SpaceDescriptor; USHORT Length; UCHAR ResourceType; UCHAR GeneralFlags; UCHAR TypeSpecificFlag; ULONGLONG Granularity; ULONGLONG AddressRangeMin; ULONGLONG AddressRangeMax; ULONGLONG TranslationOffset; ULONGLONG AddressLength; } EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR, *PEFI_ACPI_ADDRESS_SPACE_DESCRIPTOR; /* ACPI device path node */ typedef struct _EFI_ACPI_HID_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT32 HID; UINT32 UID; } EFI_ACPI_HID_DEVICE_PATH, *PEFI_ACPI_HID_DEVICE_PATH; /* Expanded ACPI device path node */ typedef struct _EFI_EXPANDED_ACPI_HID_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT32 HID; UINT32 UID; UINT32 CID; UINT8 HidStr[1]; } EFI_EXPANDED_ACPI_HID_DEVICE_PATH, *PEFI_EXPANDED_ACPI_HID_DEVICE_PATH; /* ACPI ADR device path node */ typedef struct _EFI_ACPI_ADR_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT32 ADR; } EFI_ACPI_ADR_DEVICE_PATH, *PEFI_ACPI_ADR_DEVICE_PATH; /* ATAPI device path node */ typedef struct _EFI_ATAPI_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT8 PrimarySecondary; UINT8 SlaveMaster; UINT16 Lun; } EFI_ATAPI_DEVICE_PATH, *PEFI_ATAPI_DEVICE_PATH; /* SCSI device path node */ typedef struct _EFI_SCSI_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT16 Pun; UINT16 Lun; } EFI_SCSI_DEVICE_PATH, *PEFI_SCSI_DEVICE_PATH; /* Fibre Channel device path node */ typedef struct _EFI_FIBRECHANNEL_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT32 Reserved; UINT64 WWN; UINT64 Lun; } EFI_FIBRECHANNEL_DEVICE_PATH, *PEFI_FIBRECHANNEL_DEVICE_PATH; /* Fibre Channerl EX subtype device path node */ typedef struct _EFI_FIBRECHANNELEX_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header ; UINT32 Reserved; UINT8 WWN[8]; UINT8 Lun[8]; } EFI_FIBRECHANNELEX_DEVICE_PATH, *PEFI_FIBRECHANNELEX_DEVICE_PATH; /* 1394 device path node */ typedef struct _EFI_1394_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT32 Reserved; UINT64 Guid; } EFI_1394_DEVICE_PATH, *PEFI_1394_DEVICE_PATH; /* USB device path node */ typedef struct _EFI_USB_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT8 Port; UINT8 Endpoint; } EFI_USB_DEVICE_PATH, *PEFI_USB_DEVICE_PATH; /* USB WWID device path node */ typedef struct _EFI_USB_WWID_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT16 InterfaceNumber; UINT16 VendorId; UINT16 ProductId; UINT16 SerialNumber[1]; } EFI_USB_WWID_DEVICE_PATH, *PEFI_USB_WWID_DEVICE_PATH; /* USB Class device path node */ typedef struct _EFI_USB_CLASS_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT16 VendorId; UINT16 ProductId; UINT8 DeviceClass; UINT8 DeviceSubclass; UINT8 DeviceProtocol; } EFI_USB_CLASS_DEVICE_PATH, *PEFI_USB_CLASS_DEVICE_PATH; /* SATA device path node */ typedef struct _EFI_SATA_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT16 HBAPortNumber; UINT16 PortMultiplierPortNumber; UINT16 Lun; } EFI_SATA_DEVICE_PATH, *PEFI_SATA_DEVICE_PATH; /* Device Logical Unit device path node */ typedef struct _EFI_DEVICE_LOGICAL_UNIT_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT8 Lun; } EFI_DEVICE_LOGICAL_UNIT_DEVICE_PATH, *PEFI_DEVICE_LOGICAL_UNIT_DEVICE_PATH; /* I2O device path node */ typedef struct _EFI_I2O_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT32 Tid; } EFI_I2O_DEVICE_PATH, *PEFI_I2O_DEVICE_PATH; /* MAC Address device path node */ typedef struct _EFI_MAC_ADDR_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; EFI_MAC_ADDRESS MacAddress; UINT8 IfType; } EFI_MAC_ADDR_DEVICE_PATH, *PEFI_MAC_ADDR_DEVICE_PATH; /* IPv4 device path node */ typedef struct _EFI_IPv4_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; EFI_IPv4_ADDRESS LocalIpAddress; EFI_IPv4_ADDRESS RemoteIpAddress; UINT16 LocalPort; UINT16 RemotePort; UINT16 Protocol; UCHAR StaticIpAddress; EFI_IPv4_ADDRESS GatewayIpAddress; EFI_IPv4_ADDRESS SubnetMask; } EFI_IPv4_DEVICE_PATH, *PEFI_IPv4_DEVICE_PATH; /* IPv6 device path node */ typedef struct _EFI_IPv6_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; EFI_IPv6_ADDRESS LocalIpAddress; EFI_IPv6_ADDRESS RemoteIpAddress; UINT16 LocalPort; UINT16 RemotePort; UINT16 Protocol; UCHAR IPAddressOrigin; UINT8 PrefixLength; EFI_IPv6_ADDRESS GatewayIpAddress; } EFI_IPv6_DEVICE_PATH, *PEFI_IPv6_DEVICE_PATH; /* Uniform Resource Identifiers SubType device path node */ typedef struct _EFI_URI_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT8 Uri[1]; } EFI_URI_DEVICE_PATH, *PEFI_URI_DEVICE_PATH; /* VLAN device path node */ typedef struct _EFI_VLAN_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT16 VlanId; } EFI_VLAN_DEVICE_PATH, *PEFI_VLAN_DEVICE_PATH; /* InfiniBand device path node */ typedef struct _EFI_INFINIBAND_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT32 ResourceFlags; UINT8 PortGid[16]; UINT64 ServiceId; UINT64 TargetPortId; UINT64 DeviceId; } EFI_INFINIBAND_DEVICE_PATH, *PEFI_INFINIBAND_DEVICE_PATH; /* UART device path node */ typedef struct _EFI_UART_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT32 Reserved; UINT64 BaudRate; UINT8 DataBits; UINT8 Parity; UINT8 StopBits; } EFI_UART_DEVICE_PATH, *PEFI_UART_DEVICE_PATH; /* Hard Drive device path node */ typedef struct _EFI_HARDDRIVE_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT32 PartitionNumber; UINT64 PartitionStart; UINT64 PartitionSize; UINT8 Signature[16]; UINT8 MBRType; UINT8 SignatureType; } EFI_HARDDRIVE_DEVICE_PATH, *PEFI_HARDDRIVE_DEVICE_PATH; /* CDROM device path node */ typedef struct _EFI_CDROM_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT32 BootEntry; UINT64 PartitionStart; UINT64 PartitionSize; } EFI_CDROM_DEVICE_PATH, *PEFI_CDROM_DEVICE_PATH; /* File Path device path node */ typedef struct _EFI_FILEPATH_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; WCHAR PathName[1]; } EFI_FILEPATH_DEVICE_PATH, *PEFI_FILEPATH_DEVICE_PATH; /* Media Protocol device path node */ typedef struct _EFI_MEDIA_PROTOCOL_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; EFI_GUID Protocol; } EFI_MEDIA_PROTOCOL_DEVICE_PATH, *PEFI_MEDIA_PROTOCOL_DEVICE_PATH; /* Media Firmware File SubType device path node */ typedef struct _EFI_MEDIA_FW_VOL_FILEPATH_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; EFI_GUID FvFileName; } EFI_MEDIA_FW_VOL_FILEPATH_DEVICE_PATH, *PEFI_MEDIA_FW_VOL_FILEPATH_DEVICE_PATH; /* Media Firmware Volume SubType device path node */ typedef struct _EFI_MEDIA_FW_VOL_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; EFI_GUID FvName; } EFI_MEDIA_FW_VOL_DEVICE_PATH, *PEFI_MEDIA_FW_VOL_DEVICE_PATH; /* Media relative offset range device path node */ typedef struct _EFI_MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT32 Reserved; UINT64 StartingOffset; UINT64 EndingOffset; } EFI_MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH, *PEFI_MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH; /* BIOS Boot Specification (BBS) device path node */ typedef struct _EFI_BBS_BBS_DEVICE_PATH { EFI_DEVICE_PATH_PROTOCOL Header; UINT16 DeviceType; UINT16 StatusFlag; UINT8 String[1]; } EFI_BBS_BBS_DEVICE_PATH, *PEFI_BBS_BBS_DEVICE_PATH; /* EFI device path nodes union */ typedef union _EFI_DEV_PATH { EFI_DEVICE_PATH_PROTOCOL DevPath; EFI_PCI_DEVICE_PATH Pci; EFI_PCCARD_DEVICE_PATH PcCard; EFI_MEMMAP_DEVICE_PATH MemMap; EFI_VENDOR_DEVICE_PATH Vendor; EFI_UNKNOWN_DEVICE_VENDOR_DEVICE_PATH UnknownVendor; EFI_CONTROLLER_DEVICE_PATH Controller; EFI_ACPI_HID_DEVICE_PATH Acpi; EFI_ATAPI_DEVICE_PATH Atapi; EFI_SCSI_DEVICE_PATH Scsi; EFI_FIBRECHANNEL_DEVICE_PATH FibreChannel; EFI_1394_DEVICE_PATH F1394; EFI_USB_DEVICE_PATH Usb; EFI_USB_CLASS_DEVICE_PATH UsbClass; EFI_I2O_DEVICE_PATH I2O; EFI_MAC_ADDR_DEVICE_PATH MacAddr; EFI_IPv4_DEVICE_PATH Ipv4; EFI_IPv6_DEVICE_PATH Ipv6; EFI_URI_DEVICE_PATH Uri; EFI_INFINIBAND_DEVICE_PATH InfiniBand; EFI_UART_DEVICE_PATH Uart; EFI_HARDDRIVE_DEVICE_PATH HardDrive; EFI_CDROM_DEVICE_PATH CD; EFI_FILEPATH_DEVICE_PATH FilePath; EFI_MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; EFI_BBS_BBS_DEVICE_PATH Bbs; } EFI_DEV_PATH, *PEFI_DEV_PATH; /* EFI device path node pointers union */ typedef union _EFI_DEV_PATH_PTR { PEFI_DEVICE_PATH_PROTOCOL DevPath; PEFI_PCI_DEVICE_PATH Pci; PEFI_PCCARD_DEVICE_PATH PcCard; PEFI_MEMMAP_DEVICE_PATH MemMap; PEFI_VENDOR_DEVICE_PATH Vendor; PEFI_UNKNOWN_DEVICE_VENDOR_DEVICE_PATH UnknownVendor; PEFI_CONTROLLER_DEVICE_PATH Controller; PEFI_ACPI_HID_DEVICE_PATH Acpi; PEFI_ATAPI_DEVICE_PATH Atapi; PEFI_SCSI_DEVICE_PATH Scsi; PEFI_FIBRECHANNEL_DEVICE_PATH FibreChannel; PEFI_1394_DEVICE_PATH F1394; PEFI_USB_DEVICE_PATH Usb; PEFI_USB_CLASS_DEVICE_PATH UsbClass; PEFI_I2O_DEVICE_PATH I2O; PEFI_MAC_ADDR_DEVICE_PATH MacAddr; PEFI_IPv4_DEVICE_PATH Ipv4; PEFI_IPv6_DEVICE_PATH Ipv6; PEFI_URI_DEVICE_PATH Uri; PEFI_INFINIBAND_DEVICE_PATH InfiniBand; PEFI_UART_DEVICE_PATH Uart; PEFI_HARDDRIVE_DEVICE_PATH HardDrive; PEFI_FILEPATH_DEVICE_PATH FilePath; PEFI_MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; PEFI_CDROM_DEVICE_PATH CD; PEFI_BBS_BBS_DEVICE_PATH Bbs; } EFI_DEV_PATH_PTR, *PEFI_DEV_PATH_PTR; /* EFI device path to text protocol */ typedef struct _EFI_DEVICE_PATH_TO_TEXT_PROTOCOL { PEFI_DEVICE_PATH_TO_TEXT_NODE ConvertDeviceNodeToText; PEFI_DEVICE_PATH_TO_TEXT_PATH ConvertDevicePathToText; } EFI_DEVICE_PATH_TO_TEXT_PROTOCOL, *PEFI_DEVICE_PATH_TO_TEXT_PROTOCOL; /* EFI device path from text protocol */ typedef struct _EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL { PEFI_DEVICE_PATH_FROM_TEXT_NODE ConvertTextToDeviceNode; PEFI_DEVICE_PATH_FROM_TEXT_PATH ConvertTextToDevicePath; } EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL, *PEFI_DEVICE_PATH_FROM_TEXT_PROTOCOL; /* EFI device path utility protocol */ typedef struct _EFI_DEVICE_PATH_UTILITIES_PROTOCOL { PEFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE GetDevicePathSize; PEFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH DuplicateDevicePath; PEFI_DEVICE_PATH_UTILS_APPEND_PATH AppendDevicePath; PEFI_DEVICE_PATH_UTILS_APPEND_NODE AppendDeviceNode; PEFI_DEVICE_PATH_UTILS_APPEND_INSTANCE AppendDevicePathInstance; PEFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE GetNextDevicePathInstance; PEFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE IsDevicePathMultiInstance; PEFI_DEVICE_PATH_UTILS_CREATE_NODE CreateDeviceNode; } EFI_DEVICE_PATH_UTILITIES_PROTOCOL, *PEFI_DEVICE_PATH_UTILITIES_PROTOCOL; /* PCI I/O protocol access registers */ typedef struct _EFI_PCI_IO_PROTOCOL_ACCESS { EFI_PCI_IO_PROTOCOL_IO_MEM Read; EFI_PCI_IO_PROTOCOL_IO_MEM Write; } EFI_PCI_IO_PROTOCOL_ACCESS, *PEFI_PCI_IO_PROTOCOL_ACCESS; /* PCI Root Bridge I/O protocol access registers */ typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS { EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Read; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Write; } EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS, *PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS; /* PCI I/O protocol configuration access registers */ typedef struct _EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS { EFI_PCI_IO_PROTOCOL_CONFIG Read; EFI_PCI_IO_PROTOCOL_CONFIG Write; } EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS, *PEFI_PCI_IO_PROTOCOL_CONFIG_ACCESS; /* PCI Root Bridge I/O protocol address */ typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS { UINT8 Register; UINT8 Function; UINT8 Device; UINT8 Bus; UINT32 ExtendedRegister; } EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS, *PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS; /* EFI PCI I/O protocol */ typedef struct _EFI_PCI_IO_PROTOCOL { EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollMem; EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollIo; EFI_PCI_IO_PROTOCOL_ACCESS Mem; EFI_PCI_IO_PROTOCOL_ACCESS Io; EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS Pci; EFI_PCI_IO_PROTOCOL_COPY_MEM CopyMem; EFI_PCI_IO_PROTOCOL_MAP Map; EFI_PCI_IO_PROTOCOL_UNMAP Unmap; EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; EFI_PCI_IO_PROTOCOL_FREE_BUFFER FreeBuffer; EFI_PCI_IO_PROTOCOL_FLUSH Flush; EFI_PCI_IO_PROTOCOL_GET_LOCATION GetLocation; EFI_PCI_IO_PROTOCOL_ATTRIBUTES Attributes; EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES GetBarAttributes; EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES SetBarAttributes; UINT64 RomSize; PVOID RomImage; } EFI_PCI_IO_PROTOCOL, *PEFI_PCI_IO_PROTOCOL; /* EFI PCI Root Bridge I/O protocol */ typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL { EFI_HANDLE ParentHandle; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollMem; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollIo; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Mem; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Io; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Pci; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM CopyMem; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP Map; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP Unmap; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER FreeBuffer; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH Flush; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES GetAttributes; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES SetAttributes; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION Configuration; UINT32 SegmentNumber; } EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL, *PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL; /* Describes block device */ typedef struct _EFI_BLOCK_DEVICE { LIST_ENTRY ListEntry; EFI_GUID Guid; USHORT DriveType; ULONG DriveNumber; ULONG PartitionNumber; PEFI_GUID PartitionGuid; PEFI_DEVICE_PATH_PROTOCOL DevicePath; } EFI_BLOCK_DEVICE, *PEFI_BLOCK_DEVICE; /* Describes block device I/O and DP protocols */ typedef struct _EFI_BLOCK_DEVICE_DATA { LIST_ENTRY ListEntry; PEFI_DEVICE_PATH_PROTOCOL DevicePath; PEFI_BLOCK_IO_PROTOCOL BlockIo; } EFI_BLOCK_DEVICE_DATA, *PEFI_BLOCK_DEVICE_DATA; /* Block I/O media structure */ typedef struct _EFI_BLOCK_IO_MEDIA { UINT32 MediaId; BOOLEAN RemovableMedia; BOOLEAN MediaPresent; BOOLEAN LogicalPartition; BOOLEAN ReadOnly; BOOLEAN WriteCaching; UINT32 BlockSize; UINT32 IoAlign; EFI_LBA LastBlock; EFI_LBA LowestAlignedLba; UINT32 LogicalBlocksPerPhysicalBlock; UINT32 OptimalTransferLengthGranularity; } EFI_BLOCK_IO_MEDIA, *PEFI_BLOCK_IO_MEDIA; /* EFI Block I/O protocol */ typedef struct _EFI_BLOCK_IO_PROTOCOL { UINT64 Revision; PEFI_BLOCK_IO_MEDIA Media; PEFI_BLOCK_RESET Reset; PEFI_BLOCK_READ ReadBlocks; PEFI_BLOCK_WRITE WriteBlocks; PEFI_BLOCK_FLUSH FlushBlocks; } EFI_BLOCK_IO_PROTOCOL, *PEFI_BLOCK_IO_PROTOCOL; /* EFI Block IO2 protocol */ typedef struct _EFI_BLOCK_IO2_PROTOCOL { PEFI_BLOCK_IO_MEDIA Media; PEFI_BLOCK_RESET_EX Reset; PEFI_BLOCK_READ_EX ReadBlocksEx; PEFI_BLOCK_WRITE_EX WriteBlocksEx; PEFI_BLOCK_FLUSH_EX FlushBlocksEx; } EFI_BLOCK_IO2_PROTOCOL, *PEFI_BLOCK_IO2_PROTOCOL; /* EFI Block IO2 token */ typedef struct _EFI_BLOCK_IO2_TOKEN { EFI_EVENT Event; EFI_STATUS TransactionStatus; } EFI_BLOCK_IO2_TOKEN, *PEFI_BLOCK_IO2_TOKEN; /* EFI Disk IO protocol */ typedef struct _EFI_DISK_IO_PROTOCOL { UINT64 Revision; PEFI_DISK_READ ReadDisk; PEFI_DISK_WRITE WriteDisk; } EFI_DISK_IO_PROTOCOL, *PEFI_DISK_IO_PROTOCOL; /* EFI Disk IO2 token */ typedef struct _EFI_DISK_IO2_TOKEN { EFI_EVENT Event; EFI_STATUS TransactionStatus; } EFI_DISK_IO2_TOKEN, *PEFI_DISK_IO2_TOKEN; /* EFI Disk IO2 protocol */ typedef struct _EFI_DISK_IO2_PROTOCOL { UINT64 Revision; PEFI_DISK_CANCEL_EX Cancel; PEFI_DISK_READ_EX ReadDiskEx; PEFI_DISK_WRITE_EX WriteDiskEx; PEFI_DISK_FLUSH_EX FlushDiskEx; } EFI_DISK_IO2_PROTOCOL, *PEFI_DISK_IO2_PROTOCOL; /* EFI Simple File System (SFS) protocol */ typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL { UINT64 Revision; PEFI_VOLUME_OPEN OpenVolume; } EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, *PEFI_SIMPLE_FILE_SYSTEM_PROTOCOL; /* EFI File I/O token */ typedef struct _EFI_FILE_IO_TOKEN { EFI_EVENT Event; EFI_STATUS Status; UINT_PTR BufferSize; PVOID Buffer; } EFI_FILE_IO_TOKEN, *PEFI_FILE_IO_TOKEN; /* EFI File Handle */ typedef struct _EFI_FILE_HANDLE { UINT64 Revision; PEFI_FILE_OPEN Open; PEFI_FILE_CLOSE Close; PEFI_FILE_DELETE Delete; PEFI_FILE_READ Read; PEFI_FILE_WRITE Write; PEFI_FILE_GET_POSITION GetPosition; PEFI_FILE_SET_POSITION SetPosition; PEFI_FILE_GET_INFO GetInfo; PEFI_FILE_SET_INFO SetInfo; PEFI_FILE_FLUSH Flush; PEFI_FILE_OPEN_EX OpenEx; PEFI_FILE_READ_EX ReadEx; PEFI_FILE_WRITE_EX WriteEx; PEFI_FILE_FLUSH_EX FlushEx; } EFI_FILE_HANDLE, *PEFI_FILE_HANDLE; /* EFI File Info structure */ typedef struct _EFI_FILE_INFO { UINT64 Size; UINT64 FileSize; UINT64 PhysicalSize; EFI_TIME CreateTime; EFI_TIME LastAccessTime; EFI_TIME ModificationTime; UINT64 Attribute; WCHAR FileName[1]; } EFI_FILE_INFO, *PEFI_FILE_INFO; /* EFI File System Info structure */ typedef struct _EFI_FILE_SYSTEM_INFO { UINT64 Size; UCHAR ReadOnly; UINT64 VolumeSize; UINT64 FreeSpace; UINT32 BlockSize; UINT16 VolumeLabel[1]; } EFI_FILE_SYSTEM_INFO, *PEFI_FILE_SYSTEM_INFO; /* EFI File System Volume Label */ typedef struct _EFI_FILE_SYSTEM_VOLUME_LABEL { UINT16 VolumeLabel[1]; } EFI_FILE_SYSTEM_VOLUME_LABEL, *PEFI_FILE_SYSTEM_VOLUME_LABEL; /* Load file protocol */ typedef struct _EFI_LOAD_FILE_PROTOCOL { PEFI_LOAD_FILE LoadFile; } EFI_LOAD_FILE_PROTOCOL, *PEFI_LOAD_FILE_PROTOCOL; /* EFI I/O access structure */ typedef struct _EFI_IO_ACCESS { PEFI_DEVICE_IO Read; PEFI_DEVICE_IO Write; } EFI_IO_ACCESS, *PEFI_IO_ACCESS; /* EFI Device I/O protocol */ typedef struct _EFI_DEVICE_IO_PROTOCOL { EFI_IO_ACCESS Mem; EFI_IO_ACCESS Io; EFI_IO_ACCESS Pci; PEFI_IO_MAP Map; PEFI_PCIDEV_DEVICE_PATH PciDevicePath; PEFI_IO_UNMAP Unmap; PEFI_IO_ALLOCATE_BUFFER AllocateBuffer; PEFI_IO_FLUSH Flush; PEFI_IO_FREE_BUFFER FreeBuffer; } EFI_DEVICE_IO_PROTOCOL, *PEFI_DEVICE_IO_PROTOCOL; /* EFI Hash Output union */ typedef union _EFI_HASH_OUTPUT { PUINT8 Md5Hash; PUINT8 Sha1Hash; PUINT8 Sha224Hash; PUINT8 Sha256Hash; PUINT8 Sha384Hash; PUINT8 Sha512Hash; } EFI_HASH_OUTPUT, *PEFI_HASH_OUTPUT; /* EFI Hash protocol */ typedef struct _EFI_HASH_PROTOCOL { PEFI_HASH_GET_HASH_SIZE GetHashSize; PEFI_HASH_HASH Hash; } EFI_HASH_PROTOCOL, *PEFI_HASH_PROTOCOL; /* EFI Unicode Collation protocol */ typedef struct _EFI_UNICODE_COLLATION_PROTOCOL { PEFI_UNICODE_STRICOLL StriColl; PEFI_UNICODE_METAIMATCH MetaiMatch; PEFI_UNICODE_STRLWR StrLwr; PEFI_UNICODE_STRUPR StrUpr; PEFI_UNICODE_FATTOSTR FatToStr; PEFI_UNICODE_STRTOFAT StrToFat; PUINT8 SupportedLanguages; } EFI_UNICODE_COLLATION_PROTOCOL, *PEFI_UNICODE_COLLATION_PROTOCOL; /* EFI Pixel bitmask */ typedef struct _EFI_PIXEL_BITMASK { UINT32 RedMask; UINT32 GreenMask; UINT32 BlueMask; UINT32 ReservedMask; } EFI_PIXEL_BITMASK, *PEFI_PIXEL_BITMASK; /* EFI GOP output mode information */ typedef struct _EFI_GRAPHICS_OUTPUT_MODE_INFORMATION { UINT32 Version; UINT32 HorizontalResolution; UINT32 VerticalResolution; EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; EFI_PIXEL_BITMASK PixelInformation; UINT32 PixelsPerScanLine; } EFI_GRAPHICS_OUTPUT_MODE_INFORMATION, *PEFI_GRAPHICS_OUTPUT_MODE_INFORMATION; /* EFI GOP output blt pixel */ typedef struct _EFI_GRAPHICS_OUTPUT_BLT_PIXEL { UINT8 Blue; UINT8 Green; UINT8 Red; UINT8 Reserved; } EFI_GRAPHICS_OUTPUT_BLT_PIXEL, *PEFI_GRAPHICS_OUTPUT_BLT_PIXEL; /* EFI GOP output blt pixel */ typedef union _EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION { EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixel; UINT32 Raw; } EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION, *PEFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION; /* EFI GOP output protocol mode */ typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE { UINT32 MaxMode; UINT32 Mode; PEFI_GRAPHICS_OUTPUT_MODE_INFORMATION Info; UINT_PTR SizeOfInfo; EFI_PHYSICAL_ADDRESS FrameBufferBase; UINT_PTR FrameBufferSize; } EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE, *PEFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; /* EFI GOP output protocol */ typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL { PEFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode; PEFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode; PEFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt; PEFI_GRAPHICS_OUTPUT_PROTOCOL_MODE Mode; } EFI_GRAPHICS_OUTPUT_PROTOCOL, *PEFI_GRAPHICS_OUTPUT_PROTOCOL; /* EFI UGA adapter protocol */ typedef struct _EFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL { PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL_GET_MODE GetMode; PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL_SET_MODE SetMode; PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL_BLT Blt; } EFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL, *PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL; /* EFI UGA PIXEL */ typedef struct _EFI_UNIVERSAL_GRAPHICS_BLT_PIXEL { UINT8 Blue; UINT8 Green; UINT8 Red; UINT8 Reserved; } EFI_UNIVERSAL_GRAPHICS_BLT_PIXEL, *PEFI_UNIVERSAL_GRAPHICS_BLT_PIXEL; /* EFI EDID discover protocol */ typedef struct _EFI_EDID_DISCOVERED_PROTOCOL { UINT32 SizeOfEdid; PUINT8 Edid; } EFI_EDID_DISCOVERED_PROTOCOL, *PEFI_EDID_DISCOVERED_PROTOCOL; /* EFI EDID active protocol */ typedef struct _EFI_EDID_ACTIVE_PROTOCOL { UINT32 SizeOfEdid; PUINT8 Edid; } EFI_EDID_ACTIVE_PROTOCOL, *PEFI_EDID_ACTIVE_PROTOCOL; /* EFI EDID override protocol */ typedef struct _EFI_EDID_OVERRIDE_PROTOCOL { PEFI_EDID_OVERRIDE_PROTOCOL_GET_EDID GetEdid; } EFI_EDID_OVERRIDE_PROTOCOL, *PEFI_EDID_OVERRIDE_PROTOCOL; /* EFI BBS status flags */ typedef struct _EFI_BBS_STATUS_FLAGS { UINT16 OldPosition:4; UINT16 Reserved1:4; UINT16 Enabled:1; UINT16 Failed:1; UINT16 MediaPresent:2; UINT16 Reserved2:4; } EFI_BBS_STATUS_FLAGS, *PEFI_BBS_STATUS_FLAGS; /* EFI BBS table */ typedef struct _EFI_BBS_TABLE { UINT16 BootPriority; UINT32 Bus; UINT32 Device; UINT32 Function; UINT8 Class; UINT8 SubClass; UINT16 MfgStringOffset; UINT16 MfgStringSegment; UINT16 DeviceType; EFI_BBS_STATUS_FLAGS StatusFlags; UINT16 BootHandlerOffset; UINT16 BootHandlerSegment; UINT16 DescStringOffset; UINT16 DescStringSegment; UINT32 InitPerReserved; UINT32 AdditionalIrq13Handler; UINT32 AdditionalIrq18Handler; UINT32 AdditionalIrq19Handler; UINT32 AdditionalIrq40Handler; UINT8 AssignedDriveNumber; UINT32 AdditionalIrq41Handler; UINT32 AdditionalIrq46Handler; UINT32 IBV1; UINT32 IBV2; } EFI_BBS_TABLE, *PEFI_BBS_TABLE; /* EFI ATAPI identify data */ typedef struct _EFI_ATAPI_IDENTIFY { UINT16 Raw[256]; } EFI_ATAPI_IDENTIFY, *PEFI_ATAPI_IDENTIFY; /* EFI HDD info structure */ typedef struct _EFI_HDD_INFO { UINT16 Status; UINT32 Bus; UINT32 Device; UINT32 Function; UINT16 CommandBaseAddress; UINT16 ControlBaseAddress; UINT16 BusMasterAddress; UINT8 HddIrq; EFI_ATAPI_IDENTIFY IdentifyDrive[2]; } EFI_HDD_INFO, *PEFI_HDD_INFO; /* EFI x86 EFLAGS register set */ typedef struct _EFI_EFLAGS_REG { UINT32 CF:1; UINT32 Reserved1:1; UINT32 PF:1; UINT32 Reserved2:1; UINT32 AF:1; UINT32 Reserved3:1; UINT32 ZF:1; UINT32 SF:1; UINT32 TF:1; UINT32 IF:1; UINT32 DF:1; UINT32 OF:1; UINT32 IOPL:2; UINT32 NT:1; UINT32 Reserved4:2; UINT32 VM:1; UINT32 Reserved5:14; } EFI_EFLAGS_REG, *PEFI_EFLAGS_REG; /* EFI x86 FLAGS register set */ typedef struct _EFI_FLAGS_REG { UINT16 CF:1; UINT16 Reserved1:1; UINT16 PF:1; UINT16 Reserved2:1; UINT16 AF:1; UINT16 Reserved3:1; UINT16 ZF:1; UINT16 SF:1; UINT16 TF:1; UINT16 IF:1; UINT16 DF:1; UINT16 OF:1; UINT16 IOPL:2; UINT16 NT:1; UINT16 Reserved4:1; } EFI_FLAGS_REG, *PEFI_FLAGS_REG; /* EFI x86 BYTE register set */ typedef struct _EFI_BYTE_REGS { UINT8 AL; UINT8 AH; UINT16 ReservedAX; UINT8 BL; UINT8 BH; UINT16 ReservedBX; UINT8 CL; UINT8 CH; UINT16 ReservedCX; UINT8 DL; UINT8 DH; UINT16 ReservedDX; } EFI_BYTE_REGS, *PEFI_BYTE_REGS; /* EFI x86 DWORD register set */ typedef struct _EFI_DWORD_REGS { UINT32 EAX; UINT32 EBX; UINT32 ECX; UINT32 EDX; UINT32 ESI; UINT32 EDI; EFI_EFLAGS_REG EFlags; UINT16 ES; UINT16 CS; UINT16 SS; UINT16 DS; UINT16 FS; UINT16 GS; UINT32 EBP; UINT32 ESP; } EFI_DWORD_REGS, *PEFI_DWORD_REGS; /* EFI x86 WORD register set */ typedef struct _EFI_WORD_REGS { UINT16 AX; UINT16 ReservedAX; UINT16 BX; UINT16 ReservedBX; UINT16 CX; UINT16 ReservedCX; UINT16 DX; UINT16 ReservedDX; UINT16 SI; UINT16 ReservedSI; UINT16 DI; UINT16 ReservedDI; EFI_FLAGS_REG Flags; UINT16 ReservedFlags; UINT16 ES; UINT16 CS; UINT16 SS; UINT16 DS; UINT16 FS; UINT16 GS; UINT16 BP; UINT16 ReservedBP; UINT16 SP; UINT16 ReservedSP; } EFI_WORD_REGS, *PEFI_WORD_REGS; /* EFI x86 register set union */ typedef union _EFI_IA32_REGISTER_SET { EFI_DWORD_REGS E; EFI_WORD_REGS X; EFI_BYTE_REGS H; } EFI_IA32_REGISTER_SET, *PEFI_IA32_REGISTER_SET; /* EFI legacy BIOS (CSM) support protocol */ typedef struct _EFI_LEGACY_BIOS_PROTOCOL { PEFI_LEGACY_BIOS_INT86 Int86; PEFI_LEGACY_BIOS_FARCALL86 FarCall86; PEFI_LEGACY_BIOS_CHECK_ROM CheckPciRom; PEFI_LEGACY_BIOS_INSTALL_ROM InstallPciRom; PEFI_LEGACY_BIOS_BOOT LegacyBoot; PEFI_LEGACY_BIOS_UPDATE_KEYBOARD_LED_STATUS UpdateKeyboardLedStatus; PEFI_LEGACY_BIOS_GET_BBS_INFO GetBbsInfo; PEFI_LEGACY_BIOS_SHADOW_ALL_LEGACY_OPROMS ShadowAllLegacyOproms; PEFI_LEGACY_BIOS_PREPARE_TO_BOOT_EFI PrepareToBootEfi; PEFI_LEGACY_BIOS_GET_LEGACY_REGION GetLegacyRegion; PEFI_LEGACY_BIOS_COPY_LEGACY_REGION CopyLegacyRegion; PEFI_LEGACY_BIOS_BOOT_UNCONVENTIONAL_DEVICE BootUnconventionalDevice; } EFI_LEGACY_BIOS_PROTOCOL, *PEFI_LEGACY_BIOS_PROTOCOL; /* EFI UDC attributes */ typedef struct _EFI_UDC_ATTRIBUTES { UINT8 DirectoryServiceValidity:1; UINT8 RabcaUsedFlag:1; UINT8 ExecuteHddDiagnosticsFlag:1; UINT8 Reserved:5; } EFI_UDC_ATTRIBUTES, *PEFI_UDC_ATTRIBUTES; /* EFI Service binding */ typedef struct _EFI_SERVICE_BINDING { PEFI_SERVICE_BINDING_CREATE_CHILD CreateChild; PEFI_SERVICE_BINDING_DESTROY_CHILD DestroyChild; } EFI_SERVICE_BINDING, *PEFI_SERVICE_BINDING; /* EFI driver binding protocol */ typedef struct _EFI_DRIVER_BINDING_PROTOCOL { PEFI_DRIVER_BINDING_PROTOCOL_SUPPORTED Supported; PEFI_DRIVER_BINDING_PROTOCOL_START Start; PEFI_DRIVER_BINDING_PROTOCOL_STOP Stop; UINT32 Version; EFI_HANDLE ImageHandle; EFI_HANDLE DriverBindingHandle; } EFI_DRIVER_BINDING_PROTOCOL, *PEFI_DRIVER_BINDING_PROTOCOL; /* EFI component name protocol */ typedef struct _EFI_COMPONENT_NAME_PROTOCOL { PEFI_COMPONENT_NAME_GET_DRIVER_NAME GetDriverName; PEFI_COMPONENT_NAME_GET_CONTROLLER_NAME GetControllerName; PUINT8 SupportedLanguages; } EFI_COMPONENT_NAME_PROTOCOL, *PEFI_COMPONENT_NAME_PROTOCOL; /* EFI component name2 protocol */ typedef struct _EFI_COMPONENT_NAME2_PROTOCOL { PEFI_COMPONENT_NAME2_GET_DRIVER_NAME GetDriverName; PEFI_COMPONENT_NAME2_GET_CONTROLLER_NAME GetControllerName; PUINT8 SupportedLanguages; } EFI_COMPONENT_NAME2_PROTOCOL, *PEFI_COMPONENT_NAME2_PROTOCOL; /* EFI loaded image protocol */ typedef struct _EFI_LOADED_IMAGE_PROTOCOL { UINT32 Revision; EFI_HANDLE ParentHandle; PEFI_SYSTEM_TABLE SystemTable; EFI_HANDLE DeviceHandle; PEFI_DEVICE_PATH_PROTOCOL FilePath; PVOID Reserved; UINT32 LoadOptionsSize; PVOID LoadOptions; PVOID ImageBase; UINT64 ImageSize; EFI_MEMORY_TYPE ImageCodeType; EFI_MEMORY_TYPE ImageDataType; PEFI_IMAGE_UNLOAD Unload; } EFI_LOADED_IMAGE_PROTOCOL, *PEFI_LOADED_IMAGE_PROTOCOL; /* EFI RNG protocol */ typedef struct _EFI_RNG_PROTOCOL { PEFI_RNG_GET_INFO GetInfo; PEFI_RNG_GET_RNG GetRNG; } EFI_RNG_PROTOCOL, *PEFI_RNG_PROTOCOL; /* EFI platform driver override protocol */ typedef struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL { PEFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER GetDriver; PEFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER_PATH GetDriverPath; PEFI_PLATFORM_DRIVER_OVERRIDE_DRIVER_LOADED DriverLoaded; } EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL, *PEFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL; /* EFI bus specific driver override protocol */ typedef struct _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL { PEFI_BUS_SPECIFIC_DRIVER_OVERRIDE_GET_DRIVER GetDriver; } EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL, *PEFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL; /* EFI driver family override protocol */ typedef struct _EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL { PEFI_DRIVER_FAMILY_OVERRIDE_GET_VERSION GetVersion; } EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL, *PEFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL; /* EFI EBC protocol */ typedef struct _EFI_EBC_PROTOCOL { PEFI_EBC_CREATE_THUNK CreateThunk; PEFI_EBC_UNLOAD_IMAGE UnloadImage; PEFI_EBC_REGISTER_ICACHE_FLUSH RegisterICacheFlush; PEFI_EBC_GET_VERSION GetVersion; } EFI_EBC_PROTOCOL, *PEFI_EBC_PROTOCOL; /* EFI partition header */ typedef struct _EFI_PARTITION_HEADER { EFI_TABLE_HEADER Hdr; UINT32 DirectoryAllocationNumber; UINT32 BlockSize; EFI_LBA FirstUsableLba; EFI_LBA LastUsableLba; EFI_LBA UnusableSpace; EFI_LBA FreeSpace; EFI_LBA RootFile; EFI_LBA SecutiryFile; } EFI_PARTITION_HEADER, *PEFI_PARTITION_HEADER; /* MBR partition information */ typedef struct _EFI_MBR_PARTITION_RECORD { UINT8 BootIndicator; UINT8 StartHead; UINT8 StartSector; UINT8 StartTrack; UINT8 OSIndicator; UINT8 EndHead; UINT8 EndSector; UINT8 EndTrack; UINT8 StartingLBA[4]; UINT8 SizeInLBA[4]; } EFI_MBR_PARTITION_RECORD, *PEFI_MBR_PARTITION_RECORD; /* Master Boot Record (MBR) information */ typedef struct _EFI_MASTER_BOOT_RECORD { UINT8 BootStrapCode[440]; UINT8 UniqueMbrSignature[4]; UINT8 Unknown[2]; EFI_MBR_PARTITION_RECORD Partition[4]; UINT16 Signature; } EFI_MASTER_BOOT_RECORD, *PEFI_MASTER_BOOT_RECORD; /* GUID Partition Table (GPT) header */ typedef struct _EFI_GPT_PARTITION_TABLE_HEADER { EFI_TABLE_HEADER Header; EFI_LBA MyLBA; EFI_LBA AlternateLBA; EFI_LBA FirstUsableLBA; EFI_LBA LastUsableLBA; EFI_GUID DiskGUID; EFI_LBA PartitionEntryLBA; UINT32 NumberOfPartitionEntries; UINT32 SizeOfPartitionEntry; UINT32 PartitionEntryArrayCRC32; } EFI_GPT_PARTITION_TABLE_HEADER, *PEFI_GPT_PARTITION_TABLE_HEADER; /* GUID Partition Table (GPT) partition entry */ typedef struct _EFI_GPT_PARTITION_ENTRY { EFI_GUID PartitionTypeGUID; EFI_GUID UniquePartitionGUID; EFI_LBA StartingLBA; EFI_LBA EndingLBA; UINT64 Attributes; WCHAR PartitionName[36]; } EFI_GPT_PARTITION_ENTRY, *PEFI_GPT_PARTITION_ENTRY; /* EFI file header */ typedef struct _EFI_FILE_HEADER { EFI_TABLE_HEADER Hdr; UINT32 Class; UINT32 LBALOffset; EFI_LBA Parent; UINT64 FileSize; UINT64 FileAttributes; EFI_TIME FileCreateTime; EFI_TIME FileModificationTime; EFI_GUID VendorGuid; UINT16 FileString[260]; } EFI_FILE_HEADER, *PEFI_FILE_HEADER; /* Logical Block Address List (LBA List) */ typedef struct _EFI_LBAL { EFI_TABLE_HEADER Hdr; UINT32 Class; EFI_LBA Parent; EFI_LBA Next; UINT32 ArraySize; UINT32 ArrayCount; } EFI_LBAL, *PEFI_LBAL; /* Logical Block run-length */ typedef struct _EFI_RL { EFI_LBA Start; UINT64 Length; } EFI_RL, *PEFI_RL; /* EFI UART I/O mode */ typedef struct _EFI_UART_IO_MODE { UINT32 ControlMask; UINT32 Timeout; UINT64 BaudRate; UINT32 ReceiveFifoDepth; UINT32 DataBits; UINT32 Parity; UINT32 StopBits; } EFI_UART_IO_MODE, *PEFI_UART_IO_MODE; /* EFI UART I/O protocol */ typedef struct _EFI_UART_IO_PROTOCOL { UINT32 Revision; PEFI_UART_RESET Reset; PEFI_UART_SET_ATTRIBUTES SetAttributes; PEFI_UART_SET_CONTROL_BITS SetControl; PEFI_UART_GET_CONTROL_BITS GetControl; PEFI_UART_WRITE Write; PEFI_UART_READ Read; PEFI_UART_IO_MODE Mode; } EFI_UART_IO_PROTOCOL, *PEFI_UART_IO_PROTOCOL; /* EFI IP address definition */ typedef union _EFI_IP_ADDRESS { UINT32 Addr[4]; EFI_IPv4_ADDRESS v4; EFI_IPv6_ADDRESS v6; } EFI_IP_ADDRESS, *PEFI_IP_ADDRESS; /* EFI DHCPv4 packet definition */ typedef struct _EFI_PXE_BASE_CODE_DHCPV4_PACKET { UINT8 BootpOpcode; UINT8 BootpHwType; UINT8 BootpHwAddrLen; UINT8 BootpGateHops; UINT32 BootpIdent; UINT16 BootpSeconds; UINT16 BootpFlags; UINT8 BootpCiAddr[4]; UINT8 BootpYiAddr[4]; UINT8 BootpSiAddr[4]; UINT8 BootpGiAddr[4]; UINT8 BootpHwAddr[16]; UINT8 BootpSrvName[64]; UINT8 BootpBootFile[128]; UINT32 DhcpMagik; UINT8 DhcpOptions[56]; } EFI_PXE_BASE_CODE_DHCPV4_PACKET, *PEFI_PXE_BASE_CODE_DHCPV4_PACKET; /* EFI DHCPv6 packet definition */ typedef struct _EFI_PXE_BASE_CODE_DHCPV6_PACKET { UINT32 MessageType:8; UINT32 TransactionId:24; UINT8 DhcpOptions[1024]; } EFI_PXE_BASE_CODE_DHCPV6_PACKET, *PEFI_PXE_BASE_CODE_DHCPV6_PACKET; /* EFI packet definition */ typedef union _EFI_PXE_BASE_CODE_PACKET { UINT8 Raw[1472]; EFI_PXE_BASE_CODE_DHCPV4_PACKET Dhcpv4; EFI_PXE_BASE_CODE_DHCPV6_PACKET Dhcpv6; } EFI_PXE_BASE_CODE_PACKET, *PEFI_PXE_BASE_CODE_PACKET; /* EFI ICMP error definition */ typedef struct _EFI_PXE_BASE_CODE_ICMP_ERROR { UINT8 Type; UINT8 Code; UINT16 Checksum; union { UINT32 reserved; UINT32 Mtu; UINT32 Pointer; struct { UINT16 Identifier; UINT16 Sequence; } Echo; } u; UINT8 Data[494]; } EFI_PXE_BASE_CODE_ICMP_ERROR, *PEFI_PXE_BASE_CODE_ICMP_ERROR; /* EFI TFTP error definition */ typedef struct _EFI_PXE_BASE_CODE_TFTP_ERROR { UINT8 ErrorCode; UINT8 ErrorString[127]; } EFI_PXE_BASE_CODE_TFTP_ERROR, *PEFI_PXE_BASE_CODE_TFTP_ERROR; /* EFI IP filter */ typedef struct _EFI_PXE_BASE_CODE_IP_FILTER { UINT8 Filters; UINT8 IpCnt; UINT16 reserved; EFI_IP_ADDRESS IpList[8]; } EFI_PXE_BASE_CODE_IP_FILTER, *PEFI_PXE_BASE_CODE_IP_FILTER; /* EFI ARP cache entry */ typedef struct _EFI_PXE_BASE_CODE_ARP_ENTRY { EFI_IP_ADDRESS IpAddr; EFI_MAC_ADDRESS MacAddr; } EFI_PXE_BASE_CODE_ARP_ENTRY, *PEFI_PXE_BASE_CODE_ARP_ENTRY; /* EFI route cache entry */ typedef struct _EFI_PXE_BASE_CODE_ROUTE_ENTRY { EFI_IP_ADDRESS IpAddr; EFI_IP_ADDRESS SubnetMask; EFI_IP_ADDRESS GwAddr; } EFI_PXE_BASE_CODE_ROUTE_ENTRY, *PEFI_PXE_BASE_CODE_ROUTE_ENTRY; /* EFI service list */ typedef struct _EFI_PXE_BASE_CODE_SRVLIST { UINT16 Type; UCHAR AcceptAnyResponse; UINT8 Reserved; EFI_IP_ADDRESS IpAddr; } EFI_PXE_BASE_CODE_SRVLIST, *PEFI_PXE_BASE_CODE_SRVLIST; /* EFI network discovery info */ typedef struct _EFI_PXE_BASE_CODE_DISCOVER_INFO { UCHAR UseMCast; UCHAR UseBCast; UCHAR UseUCast; UCHAR MustUseList; EFI_IP_ADDRESS ServerMCastIp; UINT16 IpCnt; EFI_PXE_BASE_CODE_SRVLIST SrvList[1]; } EFI_PXE_BASE_CODE_DISCOVER_INFO, *PEFI_PXE_BASE_CODE_DISCOVER_INFO; /* EFI TFTP info */ typedef struct _EFI_PXE_BASE_CODE_MTFTP_INFO { EFI_IP_ADDRESS MCastIp; UINT16 CPort; UINT16 SPort; UINT16 ListenTimeout; UINT16 TransmitTimeout; } EFI_PXE_BASE_CODE_MTFTP_INFO, *PEFI_PXE_BASE_CODE_MTFTP_INFO; /* EFI PXE base code mode structure */ typedef struct _EFI_PXE_BASE_CODE_MODE { UCHAR Started; UCHAR Ipv6Available; UCHAR Ipv6Supported; UCHAR UsingIpv6; UCHAR BisSupported; UCHAR BisDetected; UCHAR AutoArp; UCHAR SendGUID; UCHAR DhcpDiscoverValid; UCHAR DhcpAckReceived; UCHAR ProxyOfferReceived; UCHAR PxeDiscoverValid; UCHAR PxeReplyReceived; UCHAR PxeBisReplyReceived; UCHAR IcmpErrorReceived; UCHAR TftpErrorReceived; UCHAR MakeCallbacks; UINT8 TTL; UINT8 ToS; EFI_IP_ADDRESS StationIp; EFI_IP_ADDRESS SubnetMask; EFI_PXE_BASE_CODE_PACKET DhcpDiscover; EFI_PXE_BASE_CODE_PACKET DhcpAck; EFI_PXE_BASE_CODE_PACKET ProxyOffer; EFI_PXE_BASE_CODE_PACKET PxeDiscover; EFI_PXE_BASE_CODE_PACKET PxeReply; EFI_PXE_BASE_CODE_PACKET PxeBisReply; EFI_PXE_BASE_CODE_IP_FILTER IpFilter; UINT32 ArpCacheEntries; EFI_PXE_BASE_CODE_ARP_ENTRY ArpCache[8]; UINT32 RouteTableEntries; EFI_PXE_BASE_CODE_ROUTE_ENTRY RouteTable[8]; EFI_PXE_BASE_CODE_ICMP_ERROR IcmpError; EFI_PXE_BASE_CODE_TFTP_ERROR TftpError; } EFI_PXE_BASE_CODE_MODE, *PEFI_PXE_BASE_CODE_MODE; /* EFI PXE base code protocol */ typedef struct _EFI_PXE_BASE_CODE_PROTOCOL { UINT64 Revision; PEFI_PXE_BASE_CODE_START Start; PEFI_PXE_BASE_CODE_STOP Stop; PEFI_PXE_BASE_CODE_DHCP Dhcp; PEFI_PXE_BASE_CODE_DISCOVER Discover; PEFI_PXE_BASE_CODE_MTFTP Mtftp; PEFI_PXE_BASE_CODE_UDP_WRITE UdpWrite; PEFI_PXE_BASE_CODE_UDP_READ UdpRead; PEFI_PXE_BASE_CODE_SET_IP_FILTER SetIpFilter; PEFI_PXE_BASE_CODE_ARP Arp; PEFI_PXE_BASE_CODE_SET_PARAMETERS SetParameters; PEFI_PXE_BASE_CODE_SET_STATION_IP SetStationIp; PEFI_PXE_BASE_CODE_SET_PACKETS SetPackets; PEFI_PXE_BASE_CODE_MODE Mode; } EFI_PXE_BASE_CODE_PROTOCOL, *PEFI_PXE_BASE_CODE_PROTOCOL; /* EFI PXE base code callback protocol */ typedef struct _EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL { UINT64 Revision; PEFI_PXE_CALLBACK Callback; } EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL, *PEFI_PXE_BASE_CODE_CALLBACK_PROTOCOL; /* EFI network statistics structure */ typedef struct _EFI_NETWORK_STATISTICS { UINT64 RxTotalFrames; UINT64 RxGoodFrames; UINT64 RxUndersizeFrames; UINT64 RxOversizeFrames; UINT64 RxDroppedFrames; UINT64 RxUnicastFrames; UINT64 RxBroadcastFrames; UINT64 RxMulticastFrames; UINT64 RxCrcErrorFrames; UINT64 RxTotalBytes; UINT64 TxTotalFrames; UINT64 TxGoodFrames; UINT64 TxUndersizeFrames; UINT64 TxOversizeFrames; UINT64 TxDroppedFrames; UINT64 TxUnicastFrames; UINT64 TxBroadcastFrames; UINT64 TxMulticastFrames; UINT64 TxCrcErrorFrames; UINT64 TxTotalBytes; UINT64 Collisions; UINT64 UnsupportedProtocol; } EFI_NETWORK_STATISTICS, *PEFI_NETWORK_STATISTICS; /* EFI network mode structure */ typedef struct _EFI_SIMPLE_NETWORK_MODE { UINT32 State; UINT32 HwAddressSize; UINT32 MediaHeaderSize; UINT32 MaxPacketSize; UINT32 NvRamSize; UINT32 NvRamAccessSize; UINT32 ReceiveFilterMask; UINT32 ReceiveFilterSetting; UINT32 MaxMCastFilterCount; UINT32 MCastFilterCount; EFI_MAC_ADDRESS MCastFilter[16]; EFI_MAC_ADDRESS CurrentAddress; EFI_MAC_ADDRESS BroadcastAddress; EFI_MAC_ADDRESS PermanentAddress; UINT8 IfType; UCHAR MacAddressChangeable; UCHAR MultipleTxSupported; UCHAR MediaPresentSupported; UCHAR MediaPresent; } EFI_SIMPLE_NETWORK_MODE, *PEFI_SIMPLE_NETWORK_MODE; /* EFI network protocol structure */ typedef struct _EFI_SIMPLE_NETWORK_PROTOCOL { UINT64 Revision; PEFI_SIMPLE_NETWORK_START Start; PEFI_SIMPLE_NETWORK_STOP Stop; PEFI_SIMPLE_NETWORK_INITIALIZE Initialize; PEFI_SIMPLE_NETWORK_RESET Reset; PEFI_SIMPLE_NETWORK_SHUTDOWN Shutdown; PEFI_SIMPLE_NETWORK_RECEIVE_FILTERS ReceiveFilters; PEFI_SIMPLE_NETWORK_STATION_ADDRESS StationAddress; PEFI_SIMPLE_NETWORK_STATISTICS Statistics; PEFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC MCastIpToMac; PEFI_SIMPLE_NETWORK_NVDATA NvData; PEFI_SIMPLE_NETWORK_GET_STATUS GetStatus; PEFI_SIMPLE_NETWORK_TRANSMIT Transmit; PEFI_SIMPLE_NETWORK_RECEIVE Receive; EFI_EVENT WaitForPacket; PEFI_SIMPLE_NETWORK_MODE Mode; } EFI_SIMPLE_NETWORK_PROTOCOL, *PEFI_SIMPLE_NETWORK_PROTOCOL; /* EFI Framework MP (Multiprocessor) services protocol */ typedef struct _EFI_FRAMEWORK_MP_SERVICES_PROTOCOL { PEFI_FRAMEWORK_MP_SERVICES_GET_GENERAL_MP_INFO GetGeneralMPInfo; PEFI_FRAMEWORK_MP_SERVICES_GET_PROCESSOR_CONTEXT GetProcessorContext; PEFI_FRAMEWORK_MP_SERVICES_STARTUP_ALL_APS StartupAllAPs; PEFI_FRAMEWORK_MP_SERVICES_STARTUP_THIS_AP StartupThisAP; PEFI_FRAMEWORK_MP_SERVICES_SWITCH_BSP SwitchBSP; PEFI_FRAMEWORK_MP_SERVICES_SEND_IPI SendIPI; PEFI_FRAMEWORK_MP_SERVICES_ENABLEDISABLEAP EnableDisableAP; PEFI_FRAMEWORK_MP_SERVICES_WHOAMI WhoAmI; } EFI_FRAMEWORK_MP_SERVICES_PROTOCOL, *PEFI_FRAMEWORK_MP_SERVICES_PROTOCOL; /* EFI Framework MP (Multiprocessor) health flags union */ typedef union _EFI_FRAMEWORK_MP_HEALTH_FLAGS { struct { UINT Status:2; UINT Tested:1; UINT Reserved1:13; UINT VirtualMemoryUnavailable:1; UINT Ia32ExecutionUnavailable:1; UINT FloatingPointUnavailable:1; UINT MiscFeaturesUnavailable:1; UINT Reserved2:12; } Bits; UINT Uint32; } EFI_FRAMEWORK_MP_HEALTH_FLAGS, *PEFI_FRAMEWORK_MP_HEALTH_FLAGS; /* EFI Framework MP (Multiprocessor) health structure */ typedef struct _EFI_FRAMEWORK_MP_HEALTH { EFI_FRAMEWORK_MP_HEALTH_FLAGS Flags; UINT TestStatus; } EFI_FRAMEWORK_MP_HEALTH, *PEFI_FRAMEWORK_MP_HEALTH; /* EFI Framework processor context structure */ typedef struct _EFI_FRAMEWORK_MP_PROCESSOR_CONTEXT { UINT ApicID; BOOLEAN Enabled; EFI_FRAMEWORK_CPU_DESIGNATION Designation; EFI_FRAMEWORK_MP_HEALTH Health; UINT_PTR PackageNumber; UINT_PTR NumberOfCores; UINT_PTR NumberOfThreads; ULONGLONG ProcessorPALCompatibilityFlags; ULONGLONG ProcessorTestMask; } EFI_FRAMEWORK_MP_PROCESSOR_CONTEXT, *PEFI_FRAMEWORK_MP_PROCESSOR_CONTEXT; /* EFI MP (Multiprocessor) services protocol */ typedef struct _EFI_MP_SERVICES_PROTOCOL { PEFI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS GetNumberOfProcessors; PEFI_MP_SERVICES_GET_PROCESSOR_INFO GetProcessorInfo; PEFI_MP_SERVICES_STARTUP_ALL_APS StartupAllAPs; PEFI_MP_SERVICES_STARTUP_THIS_AP StartupThisAP; PEFI_MP_SERVICES_SWITCH_BSP SwitchBSP; PEFI_MP_SERVICES_ENABLEDISABLEAP EnableDisableAP; PEFI_MP_SERVICES_WHOAMI WhoAmI; } EFI_MP_SERVICES_PROTOCOL, *PEFI_MP_SERVICES_PROTOCOL; /* EFI processor physical location structure */ typedef struct _EFI_PROCESSOR_PHYSICAL_LOCATION { UINT32 Package; UINT32 Core; UINT32 Thread; } EFI_PROCESSOR_PHYSICAL_LOCATION, *PEFI_PROCESSOR_PHYSICAL_LOCATION; /* EFI processor information structure */ typedef struct _EFI_PROCESSOR_INFORMATION { UINT64 ProcessorId; UINT32 StatusFlag; EFI_PROCESSOR_PHYSICAL_LOCATION Location; } EFI_PROCESSOR_INFORMATION, *PEFI_PROCESSOR_INFORMATION; #endif /* __XTOS_ASSEMBLER__ */ #endif /* __XTDK_XTUEFI_H */ ================================================ FILE: xtoskrnl/CMakeLists.txt ================================================ # XT Kernel and library PROJECT(LIBXTOS) PROJECT(XTOSKRNL) # Specify include directories include_directories( ${EXECTOS_SOURCE_DIR}/sdk/xtdk ${XTOSKRNL_SOURCE_DIR}/includes) # Specify list of kernel source code files list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/ar/${ARCH}/archsup.S ${XTOSKRNL_SOURCE_DIR}/ar/${ARCH}/cpufunc.cc ${XTOSKRNL_SOURCE_DIR}/ar/${ARCH}/data.cc ${XTOSKRNL_SOURCE_DIR}/ar/${ARCH}/procsup.cc ${XTOSKRNL_SOURCE_DIR}/ar/${ARCH}/traps.cc ${XTOSKRNL_SOURCE_DIR}/ex/exports.cc ${XTOSKRNL_SOURCE_DIR}/ex/rundown.cc ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/cpu.cc ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/firmware.cc ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/ioport.cc ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/irq.cc ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/pic.cc ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/rtc.cc ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/runlevel.cc ${XTOSKRNL_SOURCE_DIR}/hl/${ARCH}/timer.cc ${XTOSKRNL_SOURCE_DIR}/hl/acpi.cc ${XTOSKRNL_SOURCE_DIR}/hl/cport.cc ${XTOSKRNL_SOURCE_DIR}/hl/data.cc ${XTOSKRNL_SOURCE_DIR}/hl/exports.cc ${XTOSKRNL_SOURCE_DIR}/hl/fbdev.cc ${XTOSKRNL_SOURCE_DIR}/hl/init.cc ${XTOSKRNL_SOURCE_DIR}/hl/ioreg.cc ${XTOSKRNL_SOURCE_DIR}/kd/data.cc ${XTOSKRNL_SOURCE_DIR}/kd/dbgio.cc ${XTOSKRNL_SOURCE_DIR}/kd/exports.cc ${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/dispatch.cc ${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/krnlinit.cc ${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/kthread.cc ${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/proc.cc ${XTOSKRNL_SOURCE_DIR}/ke/apc.cc ${XTOSKRNL_SOURCE_DIR}/ke/bootinfo.cc ${XTOSKRNL_SOURCE_DIR}/ke/crash.cc ${XTOSKRNL_SOURCE_DIR}/ke/data.cc ${XTOSKRNL_SOURCE_DIR}/ke/dispatch.cc ${XTOSKRNL_SOURCE_DIR}/ke/dpc.cc ${XTOSKRNL_SOURCE_DIR}/ke/event.cc ${XTOSKRNL_SOURCE_DIR}/ke/exports.cc ${XTOSKRNL_SOURCE_DIR}/ke/kprocess.cc ${XTOSKRNL_SOURCE_DIR}/ke/krnlinit.cc ${XTOSKRNL_SOURCE_DIR}/ke/kthread.cc ${XTOSKRNL_SOURCE_DIR}/ke/kubsan.cc ${XTOSKRNL_SOURCE_DIR}/ke/runlevel.cc ${XTOSKRNL_SOURCE_DIR}/ke/semphore.cc ${XTOSKRNL_SOURCE_DIR}/ke/shdata.cc ${XTOSKRNL_SOURCE_DIR}/ke/spinlock.cc ${XTOSKRNL_SOURCE_DIR}/ke/sysres.cc ${XTOSKRNL_SOURCE_DIR}/ke/systime.cc ${XTOSKRNL_SOURCE_DIR}/ke/timer.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/mmgr.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pagemap.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/paging.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pfault.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pfn.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pool.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pte.cc ${XTOSKRNL_SOURCE_DIR}/mm/alloc.cc ${XTOSKRNL_SOURCE_DIR}/mm/colors.cc ${XTOSKRNL_SOURCE_DIR}/mm/data.cc ${XTOSKRNL_SOURCE_DIR}/mm/exports.cc ${XTOSKRNL_SOURCE_DIR}/mm/hlpool.cc ${XTOSKRNL_SOURCE_DIR}/mm/kpool.cc ${XTOSKRNL_SOURCE_DIR}/mm/mmgr.cc ${XTOSKRNL_SOURCE_DIR}/mm/paging.cc ${XTOSKRNL_SOURCE_DIR}/mm/pfn.cc ${XTOSKRNL_SOURCE_DIR}/mm/pool.cc ${XTOSKRNL_SOURCE_DIR}/mm/pte.cc ${XTOSKRNL_SOURCE_DIR}/po/idle.cc ${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/dispatch.cc ${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/exsup.cc ${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/intrin.cc ${XTOSKRNL_SOURCE_DIR}/rtl/atomic.cc ${XTOSKRNL_SOURCE_DIR}/rtl/bitmap.cc ${XTOSKRNL_SOURCE_DIR}/rtl/data.cc ${XTOSKRNL_SOURCE_DIR}/rtl/endian.cc ${XTOSKRNL_SOURCE_DIR}/rtl/exports.cc ${XTOSKRNL_SOURCE_DIR}/rtl/guid.cc ${XTOSKRNL_SOURCE_DIR}/rtl/llist.cc ${XTOSKRNL_SOURCE_DIR}/rtl/math.cc ${XTOSKRNL_SOURCE_DIR}/rtl/memory.cc ${XTOSKRNL_SOURCE_DIR}/rtl/sha1.cc ${XTOSKRNL_SOURCE_DIR}/rtl/slist.cc ${XTOSKRNL_SOURCE_DIR}/rtl/string.cc ${XTOSKRNL_SOURCE_DIR}/rtl/time.cc ${XTOSKRNL_SOURCE_DIR}/rtl/widestr.cc) # Set module definition SPEC file set_specfile(xtoskrnl.spec xtoskrnl.exe) # Link static XTOS library add_library(libxtos ${XTOSKRNL_SOURCE}) target_link_libraries(libxtos PRIVATE xtadk) # Link kernel executable add_executable(xtoskrnl ${CMAKE_CURRENT_BINARY_DIR}/xtoskrnl.def) # Add linker libraries target_link_libraries(xtoskrnl PRIVATE libxtos) # Set proper binary name and install target set_target_properties(xtoskrnl PROPERTIES SUFFIX .exe) set_install_target(xtoskrnl "exectos/boot") # Set kernel entrypoint, imagebase address, ordinals and subsystem set_entrypoint(xtoskrnl "KeStartXtSystem") set_imagebase(xtoskrnl ${BASEADDRESS_XTOSKRNL}) set_linker_map(xtoskrnl TRUE) set_ordinals(xtoskrnl TRUE) set_subsystem(xtoskrnl native xt_native_kernel) ================================================ FILE: xtoskrnl/README.md ================================================ ## XTOSKRNL XTOSKRNL is the core kernel executable for ExectOS, providing the fundamental kernel and executive layers that operate within the XTOS kernel space. It is responsible for various core services, such as hardware abstraction, memory management, and process scheduling. The kernel contains the scheduler (sometimes referred to as the Dispatcher), the cache, object, and memory managers, the security manager, and other executive components described below. ## Kernel Parameters Kernel parameters are XTOS boot-time options used to ensure proper initialization and handling of hardware peripherals. These parameters can be configured either temporarily by editing the boot entry in the bootloader’s selection menu, or permanently by modifying the XTLDR configuration file. The following is a consolidated list of available kernel parameters: * **CLOCK**: Specifies the primary hardware source used to drive the periodic system clock interrupts and the thread scheduler tick. Valid values include `LAPIC` (Local APIC Timer), `HPET` (High Precision Event Timer), and `PIT` (Legacy Programmable Interval Timer). If this parameter is omitted, the kernel will autonomously probe the hardware and select the most optimal clock source for the current CPU topology, (defaulting to the Local APIC on modern systems. * **MAXCPUS**: Specifies the maximum number of logical processors the kernel is allowed to initialize and schedule. Setting `MAXCPUS=1` explicitly disables Symmetric Multiprocessing (SMP), restricting execution exclusively to the Boot Strap Processor (BSP) and ignoring all Application Processors (APs). * **NOX2APIC**: Explicitly disables x2APIC support. When specified, the kernel bypasses hardware feature detection for x2APIC and forces the use of the classic, memory-mapped (MMIO) xAPIC mode. This parameter is particularly useful for troubleshooting interrupt routing issues or ensuring compatibility with specific hypervisors and legacy emulators. * **NOXPA**: Disables PAE or LA57 support, depending on the CPU architecture. This parameter is handled by the bootloader, which configures paging and selects the appropriate Page Map Level (PML) before transferring control to the kernel. * **TIMER**: Designates the hardware counter used for high-resolution performance tracking (Query Performance Counter) and microsecond execution stalls. Valid values include `TSC` (Invariant Time Stamp Counter), `HPET`, `ACPI` (or `PM`) for the ACPI Power Management Timer, and `PIT`. If not specified, the kernel evaluates hardware capabilities and defaults to the most precise and reliable counter available (e.g., Invariant TSC). ## Source Code The source code of the kernel is organized into subsystem-specific directories. Each directory name also defines the corresponding C++ namespace in which the subsystem's classes and routines reside. These subsystems include: * Ar - Architecture-specific Library * Ex - Kernel Executive * Hl - Hardware Layer * Kd - Kernel Debugger * Ke - Core Kernel Library * Mm - Memory Manager * Po - Plug&Play and Power Manager * Rtl - Runtime library ### AR: Architecture Library This module contains functions specific to the processor architecture. These include routines for enabling and disabling interrupts, retrieving the faulting address on a page fault, querying CPUID information, and performing very early processor initialization. This module contains only CPU architecture-specific code, with no manufacturer or board-specific implementations. ### EX: Kernel Executive The Kernel Executive provides services for allocating system memory from paged and non-paged pools. It also supplies synchronization primitives such as pushlocks and fast mutexes, routines for interlocked memory access, and support for worker threads. ### HL: Hardware Layer The Hardware Layer is an abstraction layer between the physical hardware and the rest of the operating system. It is designed to abstract away hardware differences, providing a consistent platform on which the kernel and applications can run. ### KD: Kernel Debugger The Kernel Debugger (KD) subsystem provides debugging support for the kernel. The KD is initialized early in the boot process to facilitate debugging from the very beginning of the kernel's execution. ### KE: Kernel Library The Core Kernel Library implements the core functionality upon which the rest of the system depends. This includes fundamental low-level operations, such as routing hardware interrupts and managing dispatcher objects. ### MM: Memory Manager The Memory Manager is one of the core subsystems. It manages virtual memory, controls memory protection, and handles paging memory between physical RAM and secondary storage. It also implements a general-purpose allocator for physical memory. ### PO: Plug&Play and Power Manager This subsystem handles power management events, such as shutdown or standby. It also manages Plug and Play (PnP), supporting device detection and installation at boot time. Furthermore, it is responsible for starting and stopping devices on demand. ### RTL: Runtime Library The Runtime Library provides a kernel-mode implementation of common C library functions. It includes many utility routines, for use by other kernel components. ## Function Naming Convention All kernel functions adhere to a strict naming convention to enhance code readability and maintainability. The structure of all public interfaces exposed by the kernel are generally composed of three parts: <Prefix><Operation><Object> The prefix identifies the component to which the function belongs. For example, consider the **KeInitializeThread()** routine: * **Ke** - The prefix indicates a routine belonging to the Core Kernel Library (Ke). * **Initialize** - The operation performed by the function. * **Thread** - The object on which the operation is performed. For all C++ code inside the kernel the naming model has evolved. Consider the **KE::KThread::InitializeThread()** routine: * **KE** - The namespace replaces the prefix and indicates the subsystem. Namespaces are written in uppercase and no longer use the trailing p for private routines, because classes use C++ visibility to control access. * **KThread** - Within each namespace, related functionality is grouped into classes, which encapsulate variables and methods. * **InitializeThread** - Method names follow the `` pattern. ================================================ FILE: xtoskrnl/ar/amd64/archsup.S ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ar/amd64/archsup.S * DESCRIPTION: Provides AMD64 architecture features not implementable in C * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include #include .altmacro .text /** * Creates a trap or interrupt handler for the specified vector. * * @param Vector * Supplies a trap/interrupt vector number. * * @param Type * Specifies whether the handler is designed to handle an interrupt or a trap. * * @return This macro does not return any value. * * @since XT 1.0 */ .macro ArCreateHandler Vector Type .global Ar\Type\Vector Ar\Type\Vector: /* Check handler type */ .ifc \Type,Trap /* Push fake error code for non-error vector traps */ .if \Vector != 8 && \Vector != 10 && \Vector != 11 && \Vector != 12 && \Vector != 13 && \Vector != 14 && \Vector != 17 && \Vector != 30 push $0 .endif .else /* Push fake error code for interrupts */ push $0 .endif /* Push vector number */ push $\Vector /* Push General Purpose Registers */ push %rbp push %rdi push %rsi push %r15 push %r14 push %r13 push %r12 push %r11 push %r10 push %r9 push %r8 push %rdx push %rcx push %rbx push %rax /* Reserve space for other registers and point RBP to the trap frame */ sub $(KTRAP_FRAME_SIZE - KTRAP_FRAME_REGISTERS_SIZE), %rsp lea (%rsp), %rbp /* Store segment selectors */ mov %gs, KTRAP_FRAME_SegGs(%rbp) mov %fs, KTRAP_FRAME_SegFs(%rbp) mov %es, KTRAP_FRAME_SegEs(%rbp) mov %ds, KTRAP_FRAME_SegDs(%rbp) /* Store debug registers */ mov %dr7, %rax mov %rax, KTRAP_FRAME_Dr7(%rbp) mov %dr6, %rax mov %rax, KTRAP_FRAME_Dr6(%rbp) mov %dr3, %rax mov %rax, KTRAP_FRAME_Dr3(%rbp) mov %dr2, %rax mov %rax, KTRAP_FRAME_Dr2(%rbp) mov %dr1, %rax mov %rax, KTRAP_FRAME_Dr1(%rbp) mov %dr0, %rax mov %rax, KTRAP_FRAME_Dr0(%rbp) /* Store CR2 and CR3 */ mov %cr3, %rax mov %rax, KTRAP_FRAME_Cr3(%rbp) mov %cr2, %rax mov %rax, KTRAP_FRAME_Cr2(%rbp) /* Store MxCsr register */ stmxcsr KTRAP_FRAME_MxCsr(%rbp) /* Store XMM registers */ movdqa %xmm15, KTRAP_FRAME_Xmm15(%rbp) movdqa %xmm14, KTRAP_FRAME_Xmm14(%rbp) movdqa %xmm13, KTRAP_FRAME_Xmm13(%rbp) movdqa %xmm12, KTRAP_FRAME_Xmm12(%rbp) movdqa %xmm11, KTRAP_FRAME_Xmm11(%rbp) movdqa %xmm10, KTRAP_FRAME_Xmm10(%rbp) movdqa %xmm9, KTRAP_FRAME_Xmm9(%rbp) movdqa %xmm8, KTRAP_FRAME_Xmm8(%rbp) movdqa %xmm7, KTRAP_FRAME_Xmm7(%rbp) movdqa %xmm6, KTRAP_FRAME_Xmm6(%rbp) movdqa %xmm5, KTRAP_FRAME_Xmm5(%rbp) movdqa %xmm4, KTRAP_FRAME_Xmm4(%rbp) movdqa %xmm3, KTRAP_FRAME_Xmm3(%rbp) movdqa %xmm2, KTRAP_FRAME_Xmm2(%rbp) movdqa %xmm1, KTRAP_FRAME_Xmm1(%rbp) movdqa %xmm0, KTRAP_FRAME_Xmm0(%rbp) /* Test previous mode and swap GS if needed */ movl $0, KTRAP_FRAME_PreviousMode(%rbp) mov KTRAP_FRAME_SegCs(%rbp), %ax and $3, %al mov %al, KTRAP_FRAME_PreviousMode(%rbp) /* Skip swapgs as the interrupt originated from kernel mode */ jz Dispatch\Type\Vector swapgs Dispatch\Type\Vector: /* Set up trap frame pointer for the dispatcher and clear the direction flag */ mov %rsp, %rcx cld /* Preserve the original stack pointer */ mov %rsp, %rbx /* Force stack alignment */ and $-16, %rsp /* Allocate 32 bytes of shadow space */ sub $32, %rsp .ifc \Type,Trap /* Pass to the trap dispatcher */ call ArDispatchTrap .else /* Pass to the interrupt dispatcher */ call ArDispatchInterrupt .endif /* Restore the original trap frame stack pointer */ mov %rbx, %rsp /* Test previous mode and swapgs if needed */ testb $1, KTRAP_FRAME_PreviousMode(%rbp) jz RestoreState\Type\Vector cli swapgs RestoreState\Type\Vector: /* Restore XMM registers */ movdqa KTRAP_FRAME_Xmm0(%rbp), %xmm0 movdqa KTRAP_FRAME_Xmm1(%rbp), %xmm1 movdqa KTRAP_FRAME_Xmm2(%rbp), %xmm2 movdqa KTRAP_FRAME_Xmm3(%rbp), %xmm3 movdqa KTRAP_FRAME_Xmm4(%rbp), %xmm4 movdqa KTRAP_FRAME_Xmm5(%rbp), %xmm5 movdqa KTRAP_FRAME_Xmm6(%rbp), %xmm6 movdqa KTRAP_FRAME_Xmm7(%rbp), %xmm7 movdqa KTRAP_FRAME_Xmm8(%rbp), %xmm8 movdqa KTRAP_FRAME_Xmm9(%rbp), %xmm9 movdqa KTRAP_FRAME_Xmm10(%rbp), %xmm10 movdqa KTRAP_FRAME_Xmm11(%rbp), %xmm11 movdqa KTRAP_FRAME_Xmm12(%rbp), %xmm12 movdqa KTRAP_FRAME_Xmm13(%rbp), %xmm13 movdqa KTRAP_FRAME_Xmm14(%rbp), %xmm14 movdqa KTRAP_FRAME_Xmm15(%rbp), %xmm15 /* Load MxCsr register */ ldmxcsr KTRAP_FRAME_MxCsr(%rbp) /* Free stack space */ add $(KTRAP_FRAME_SIZE - KTRAP_FRAME_REGISTERS_SIZE), %rsp /* Pop General Purpose Registers */ pop %rax pop %rbx pop %rcx pop %rdx pop %r8 pop %r9 pop %r10 pop %r11 pop %r12 pop %r13 pop %r14 pop %r15 pop %rsi pop %rdi pop %rbp /* Skip error code and vector number, then return */ add $(2 * 8), %rsp iretq .endm /* Populate common interrupt and trap handlers */ .irp i,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F .irp j,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F ArCreateHandler 0x\i\j Interrupt ArCreateHandler 0x\i\j Trap .endr .endr /* Define array of pointers to the interrupt handlers */ .global ArInterruptEntry ArInterruptEntry: .irp i,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F .irp j,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F .quad ArInterrupt0x\i\j .endr .endr /* Define array of pointers to the trap handlers */ .global ArTrapEntry ArTrapEntry: .irp i,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F .irp j,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F .quad ArTrap0x\i\j .endr .endr /** * Enables eXtended Physical Addressing (XPA). * * @param PageMap * Supplies a pointer to the page map to be used. * * @return This routine does not return any value. * * @since XT 1.0 */ .global ArEnableExtendedPhysicalAddressing ArEnableExtendedPhysicalAddressing: /* Save the original CR4 register */ movq %cr4, %rax /* Save the state of stack pointer and non-volatile registers */ movq %rsp, XpaRegisterSaveArea(%rip) movq %rbp, XpaRegisterSaveArea+0x08(%rip) movq %rax, XpaRegisterSaveArea+0x10(%rip) movq %rbx, XpaRegisterSaveArea+0x18(%rip) /* Save the original CR0 register */ movq %cr0, %rbp /* Load temporary GDT required for mode transitions */ leaq XpaTemporaryGdtDesc(%rip), %rax movq %rax, XpaTemporaryGdtBase(%rip) lgdtq XpaTemporaryGdtSize(%rip) /* Load addresses for entering compatibility mode and re-entering long mode */ leaq XpaEnterCompatMode(%rip), %rax leaq XpaEnterLongMode(%rip), %rbx /* Push the 32-bit code segment selector and the target address for a far jump */ pushq $KGDT_R0_CMCODE pushq %rax /* Perform a far return to switch to 32-bit compatibility mode */ lretq XpaEnterCompatMode: /* Enter 32-bit compatibility mode */ .code32 /* Store the PageMap pointer on the stack for future use */ pushl %ecx /* Set the stack segment to the 32-bit data segment selector */ movl $KGDT_R0_DATA, %eax movl %eax, %ss /* Disable PGE and PCIDE to ensure all TLB entries will be flushed */ movl %cr4, %eax andl $~(CR4_PGE | CR4_PCIDE), %eax movl %eax, %cr4 /* Temporarily disable paging */ movl %ebp, %eax andl $~CR0_PG, %eax movl %eax, %cr0 /* Disable Long Mode as prerequisite for enabling 5-level paging */ movl $X86_MSR_EFER, %ecx rdmsr andl $~X86_MSR_EFER_LME, %eax wrmsr /* Transition to 5-level paging (PML5/LA57) */ movl %cr4, %eax orl $CR4_LA57, %eax movl %eax, %cr4 /* Restore the PageMap pointer from the stack and load it into CR3 */ popl %ecx movl %ecx, %cr3 /* Re-enable Long Mode */ movl $X86_MSR_EFER, %ecx rdmsr orl $X86_MSR_EFER_LME, %eax wrmsr /* Restore CR0 with paging enabled and flush the instruction pipeline */ movl %ebp, %cr0 call XpaFlushInstructions XpaFlushInstructions: /* Push the 64-bit code segment selector and the target address for a far jump */ pushl $KGDT_R0_CODE pushl %ebx /* Perform a far return to switch to 64-bit long mode */ lretl XpaEnterLongMode: /* Enter 64-bit long mode */ .code64 /* Restore the stack pointer and non-volatile registers */ movq XpaRegisterSaveArea(%rip), %rsp movq XpaRegisterSaveArea+8(%rip), %rbp movq XpaRegisterSaveArea+0x10(%rip), %rax movq XpaRegisterSaveArea+0x18(%rip), %rbx /* Restore the original CR4 register with LA57 bit set */ orq $CR4_LA57, %rax movq %rax, %cr4 /* Return to the caller */ retq /* Data section for saving registers and temporary GDT */ XpaRegisterSaveArea: .quad 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 XpaTemporaryGdtSize: .short ArEnableExtendedPhysicalAddressingEnd - XpaTemporaryGdtDesc - 1 XpaTemporaryGdtBase: .quad 0x0000000000000000 XpaTemporaryGdtDesc: .quad 0x0000000000000000, 0x00CF9A000000FFFF, 0x00AF9A000000FFFF, 0x00CF92000000FFFF .global ArEnableExtendedPhysicalAddressingEnd ArEnableExtendedPhysicalAddressingEnd: /** * Handles a spurious interrupt allowing it to end up. * * @return This routine does not return any value. * * @since XT 1.0 */ .global ArHandleSpuriousInterrupt ArHandleSpuriousInterrupt: iretq /** * Starts an application processor (AP). * * @return This routine does not return any value. * * @since XT 1.0 */ .global ArStartApplicationProcessor ArStartApplicationProcessor: /* Enter 16-bit real mode */ .code16 /* Disable interrupts and clear direction flag */ cli cld /* Establish a flat addressing baseline */ movw %cs, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss /* Calculate absolute physical base address */ xorl %ebx, %ebx movw %cs, %bx shll $4, %ebx /* Set up a temporary stack for the AP initialization */ movl %ebx, %esp addl $0x1000, %esp /* Load the temporary Global Descriptor Table */ leal (ApTemporaryGdtDesc - ArStartApplicationProcessor)(%ebx), %eax movl %eax, (ApTemporaryGdtBase - ArStartApplicationProcessor) lgdtl (ApTemporaryGdtSize - ArStartApplicationProcessor) /* Enable Protected Mode */ movl %cr0, %eax orl $0x01, %eax movl %eax, %cr0 /* Far return to enter 32-bit protected mode */ leal (ApEnterProtectedMode - ArStartApplicationProcessor)(%ebx), %eax pushl $KGDT_R0_CMCODE pushl %eax lretl ApEnterProtectedMode: /* Enter 32-bit protected mode */ .code32 /* Setup all data segment registers */ movw $KGDT_R0_DATA, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss xorw %ax, %ax movw %ax, %fs movw %ax, %gs /* Locate PROCESSOR_START_BLOCK structure */ leal (ArStartApplicationProcessorEnd - ArStartApplicationProcessor)(%ebx), %edi /* Load CR4 from BSP, but mask PCIDE and PGE */ movl PROCESSOR_START_BLOCK_Cr4(%edi), %eax andl $~(CR4_PGE | CR4_PCIDE), %eax movl %eax, %cr4 /* Load the Kernel Page Directory Base from BSP */ movl PROCESSOR_START_BLOCK_Cr3(%edi), %eax movl %eax, %cr3 /* Enable Long Mode and No-Execute */ movl $X86_MSR_EFER, %ecx rdmsr orl $(X86_MSR_EFER_LME | X86_MSR_EFER_NXE), %eax wrmsr /* Enable Paging */ movl %cr0, %eax orl $CR0_PG, %eax movl %eax, %cr0 /* Far return to enter 64-bit long mode */ leal (ApEnterLongMode - ArStartApplicationProcessor)(%ebx), %eax pushl $KGDT_R0_CODE pushl %eax lretl ApEnterLongMode: /* Enter 64-bit long mode */ .code64 /* Clear all segment registers */ xorw %ax, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss movw %ax, %fs movw %ax, %gs /* Zero-extend EDI into RDI to ensure safe 64-bit pointer usage */ movl %edi, %edi /* Load dedicated Stack for AP */ movq PROCESSOR_START_BLOCK_Stack(%rdi), %rsp /* Save the pointer to PROCESSOR_START_BLOCK */ movq %rdi, %rcx pushq %rdi /* Call the EntryPoint routine */ movq PROCESSOR_START_BLOCK_EntryPoint(%rdi), %rax call *%rax /* Fire the breakpoint and halt if the entry point returns */ .ApNoReturnPoint: int $0x03 hlt jmp .ApNoReturnPoint /* Data section for temporary GDT */ .align 8 ApTemporaryGdtSize: .short ArStartApplicationProcessorEnd - ApTemporaryGdtDesc - 1 ApTemporaryGdtBase: .quad 0x0000000000000000 ApTemporaryGdtDesc: .quad 0x0000000000000000, 0x00CF9A000000FFFF, 0x00AF9A000000FFFF, 0x00CF92000000FFFF .global ArStartApplicationProcessorEnd ArStartApplicationProcessorEnd: ================================================ FILE: xtoskrnl/ar/amd64/cpufunc.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ar/amd64/cpufunc.cc * DESCRIPTION: Routines to provide access to special AMD64 CPU instructions * DEVELOPERS: Rafal Kupiec */ #include /** * Instructs the processor to clear the interrupt flag. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::ClearInterruptFlag(VOID) { __asm__ volatile("cli"); } /** * Retrieves a various amount of information about the CPU. * * @param Registers * Supplies a pointer to the structure containing all the necessary registers and leafs for CPUID. * * @return This routine returns TRUE if CPUID function could be executed, FALSE otherwise. * * @since XT 1.0 */ XTCDECL BOOLEAN AR::CpuFunctions::CpuId(IN OUT PCPUID_REGISTERS Registers) { UINT32 MaxLeaf; /* Get highest function ID available */ __asm__ volatile("cpuid" : "=a" (MaxLeaf) : "a" (Registers->Leaf & 0x80000000) : "rbx", "rcx", "rdx"); /* Check if CPU supports this command */ if(Registers->Leaf > MaxLeaf) { /* Cannot call it, return FALSE */ return FALSE; } /* Execute CPUID function */ __asm__ volatile("cpuid" : "=a" (Registers->Eax), "=b" (Registers->Ebx), "=c" (Registers->Ecx), "=d" (Registers->Edx) : "a" (Registers->Leaf), "c" (Registers->SubLeaf)); /* Return TRUE */ return TRUE; } /** * Partially flushes the Translation Lookaside Buffer (TLB) * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::FlushTlb(VOID) { /* Flush the TLB by resetting the CR3 */ WriteControlRegister(3, ReadControlRegister(3)); } /** * Gets the RFLAGS register. * * @return This routine returns the RFLAGS register. * * @since XT 1.0 */ XTCDECL ULONG AR::CpuFunctions::GetCpuFlags(VOID) { ULONG_PTR Flags; /* Get RFLAGS register */ __asm__ volatile("pushf\n" "pop %0\n" : "=rm" (Flags) : : "memory"); /* Return flags */ return Flags; } /** * Gets the address of the current stack register. * * @return This routine returns the current stack pointer. * * @since XT 1.0 */ XTASSEMBLY XTCDECL ULONG_PTR AR::CpuFunctions::GetStackPointer(VOID) { /* Get current stack pointer */ __asm__ volatile("movq %%rsp, %%rax\n" "retq\n" : : :); } /** * Halts the central processing unit (CPU). * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::Halt(VOID) { __asm__ volatile("hlt"); } /** * Checks whether interrupts are enabled or not. * * @return This routine returns TRUE if interrupts are enabled, or FALSE otherwise. * * @since XT 1.0 */ XTCDECL BOOLEAN AR::CpuFunctions::InterruptsEnabled(VOID) { ULONG_PTR Flags; /* Get RFLAGS register */ Flags = GetCpuFlags(); /* Check if interrupts are enabled and return result */ return (Flags & X86_EFLAGS_IF_MASK) ? TRUE : FALSE; } /** * Invalidates the TLB (Translation Lookaside Buffer) for specified virtual address. * * @param Address * Suuplies a virtual address whose associated TLB entry will be invalidated. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::InvalidateTlbEntry(IN PVOID Address) { __asm__ volatile("invlpg (%0)" : : "b" (Address) : "memory"); } /** * Loads the value in the source operand into the global descriptor table register (GDTR). * * @param Source * Specifies a memory location that contains the base address of GDT. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::LoadGlobalDescriptorTable(IN PVOID Source) { __asm__ volatile("lgdt %0" : : "m" (*(PSHORT)Source) : "memory"); } /** * Loads the value in the source operand into the interrupt descriptor table register (IDTR). * * @param Source * Specifies a memory location that contains the base address of IDT. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::LoadInterruptDescriptorTable(IN PVOID Source) { __asm__ volatile("lidt %0" : : "m" (*(PSHORT)Source) : "memory"); } /** * Loads the value in the source operand into the local descriptor table register (LDTR). * * @param Source * Specifies a selector value. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::LoadLocalDescriptorTable(IN USHORT Source) { __asm__ volatile("lldtw %0" : : "g" (Source)); } /** * Loads the value in the source operand into the MXCSR register * * @param Source * Supplies a source value to be loaded into the MXCSR register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::LoadMxcsrRegister(IN ULONG Source) { __asm__ volatile("ldmxcsr %0" : : "m" (Source)); } /** * Loads source data into specified segment. * * @param Segment * Supplies a segment identification. * * @param Source * Supplies a pointer to the memory area containing data that will be loaded into specified segment. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::LoadSegment(IN USHORT Segment, IN ULONG Source) { switch(Segment) { case SEGMENT_CS: /* Load CS Segment */ __asm__ volatile("mov %0, %%rax\n" "push %%rax\n" "lea label(%%rip), %%rax\n" "push %%rax\n" "lretq\n" "label:" : : "ri" ((ULONGLONG)Source) : "rax"); break; case SEGMENT_DS: /* Load DS Segment */ __asm__ volatile("movl %0, %%ds" : : "r" (Source)); break; case SEGMENT_ES: /* Load ES Segment */ __asm__ volatile("movl %0, %%es" : : "r" (Source)); break; case SEGMENT_FS: /* Load FS Segment */ __asm__ volatile("movl %0, %%fs" : : "r" (Source)); break; case SEGMENT_GS: /* Load GS Segment */ __asm__ volatile("movl %0, %%gs" : : "r" (Source)); break; /* Load SS Segment */ case SEGMENT_SS: __asm__ volatile("movl %0, %%ss" : : "r" (Source)); break; } } /** * Loads Task Register (TR) with a segment selector that points to TSS. * * @param Source * Supplies the segment selector in the GDT describing the TSS. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::LoadTaskRegister(USHORT Source) { __asm__ volatile("ltr %0" : : "rm" (Source)); } /** * Orders memory accesses as seen by other processors. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::MemoryBarrier(VOID) { LONG Barrier; __asm__ volatile("lock; orl $0, %0;" : : "m"(Barrier)); } /** * Reads the specified CPU control register and returns its value. * * @param ControlRegister * Supplies a number of a control register which controls the general behavior of a CPU. * * @return This routine returns the value stored in the control register. * * @since XT 1.0 */ XTCDECL ULONG_PTR AR::CpuFunctions::ReadControlRegister(IN USHORT ControlRegister) { ULONG_PTR Value; /* Read a value from specified CR register */ switch(ControlRegister) { case 0: /* Read value from CR0 */ __asm__ volatile("mov %%cr0, %0" : "=r" (Value) : : "memory"); break; case 2: /* Read value from CR2 */ __asm__ volatile("mov %%cr2, %0" : "=r" (Value) : : "memory"); break; case 3: /* Read value from CR3 */ __asm__ volatile("mov %%cr3, %0" : "=r" (Value) : : "memory"); break; case 4: /* Read value from CR4 */ __asm__ volatile("mov %%cr4, %0" : "=r" (Value) : : "memory"); break; case 8: /* Read value from CR8 */ __asm__ volatile("mov %%cr8, %0" : "=r" (Value) : : "memory"); break; default: /* Invalid control register set */ Value = 0; break; } /* Return value read from given CR register */ return Value; } /** * Reads the specified CPU debug register and returns its value. * * @param DebugRegister * Supplies a number of a debug register to read from. * * @return This routine returns the value stored in the specified debug register. * * @since XT 1.0 */ XTCDECL ULONG_PTR AR::CpuFunctions::ReadDebugRegister(IN USHORT DebugRegister) { ULONG_PTR Value; /* Read a value from specified DR register */ switch(DebugRegister) { case 0: /* Read value from DR0 */ __asm__ volatile("mov %%dr0, %0" : "=r" (Value)); break; case 1: /* Read value from DR1 */ __asm__ volatile("mov %%dr1, %0" : "=r" (Value)); break; case 2: /* Read value from DR2 */ __asm__ volatile("mov %%dr2, %0" : "=r" (Value)); break; case 3: /* Read value from DR3 */ __asm__ volatile("mov %%dr3, %0" : "=r" (Value)); break; case 4: /* Read value from DR4 */ __asm__ volatile("mov %%dr4, %0" : "=r" (Value)); break; case 5: /* Read value from DR5 */ __asm__ volatile("mov %%dr5, %0" : "=r" (Value)); break; case 6: /* Read value from DR6 */ __asm__ volatile("mov %%dr6, %0" : "=r" (Value)); break; case 7: /* Read value from DR7 */ __asm__ volatile("mov %%dr7, %0" : "=r" (Value)); break; default: /* Invalid debug register set */ Value = 0; break; } /* Return value read from given DR register */ return Value; } /** * Reads quadword from a memory location specified by an offset relative to the beginning of the GS segment. * * @param Offset * Specifies the offset from the beginning of GS segment. * * @return This routine returns the value read from the specified memory location relative to GS segment. * * @since XT 1.0 */ XTCDECL ULONGLONG AR::CpuFunctions::ReadGSQuadWord(ULONG Offset) { ULONGLONG Value; /* Read quadword from GS segment */ __asm__ volatile("movq %%gs:%a[Offset], %q[Value]" : [Value] "=r" (Value) : [Offset] "ir" (Offset)); return Value; } /** * Reads a 64-bit value from the requested Model Specific Register (MSR). * * @param Register * Supplies the MSR to read. * * @return This routine returns the 64-bit MSR value. * * @since XT 1.0 */ XTCDECL ULONGLONG AR::CpuFunctions::ReadModelSpecificRegister(IN ULONG Register) { ULONG Low, High; __asm__ volatile("rdmsr" : "=a" (Low), "=d" (High) : "c" (Register)); return ((ULONGLONG)High << 32) | Low; } /** * Reads the contents of the MXCSR control/status register. * * @return This routine returns the contents of the MXCSR register as a 32-bit unsigned integer value. * * @since XT 1.0 */ XTCDECL UINT AR::CpuFunctions::ReadMxCsrRegister(VOID) { return __builtin_ia32_stmxcsr(); } /** * Reads the current value of the CPU's time-stamp counter. * * @return This routine returns the current instruction cycle count since the processor was started. * * @since XT 1.0 */ XTCDECL ULONGLONG AR::CpuFunctions::ReadTimeStampCounter(VOID) { ULONGLONG Low, High; __asm__ volatile("rdtsc" : "=a" (Low), "=d" (High)); return ((ULONGLONG)High << 32) | Low; } /** * Reads the current value of the CPU's time-stamp counter and processor ID. * * @param TscAux * Supplies a pointer to a variable that receives the auxiliary TSC information (IA32_TSC_AUX). * * @return This routine returns the current instruction cycle count since the processor was last reset. * * @since XT 1.0 */ XTCDECL ULONGLONG AR::CpuFunctions::ReadTimeStampCounterProcessor(OUT PULONG TscAux) { ULONG Low, High; /* Execute the RDTSCP instruction */ __asm__ volatile("rdtscp" : "=a" (Low), "=d" (High), "=c" (*TscAux) ); /* Combine the two 32-bit registers into a single 64-bit unsigned integer and return the value */ return ((ULONGLONG)High << 32) | Low; } /** * Orders memory accesses as seen by other processors, without fence. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::ReadWriteBarrier(VOID) { __asm__ volatile("" : : : "memory"); } /** * Instructs the processor to set the interrupt flag. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::SetInterruptFlag(VOID) { __asm__ volatile("sti"); } /** * Stores GDT register into the given memory area. * * @param Destination * Supplies a pointer to the memory area where GDT will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::StoreGlobalDescriptorTable(OUT PVOID Destination) { __asm__ volatile("sgdt %0" : "=m" (*(PSHORT)Destination) : : "memory"); } /** * Stores IDT register into the given memory area. * * @param Destination * Supplies a pointer to the memory area where IDT will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::StoreInterruptDescriptorTable(OUT PVOID Destination) { __asm__ volatile("sidt %0" : "=m" (*(PSHORT)Destination) : : "memory"); } /** * Stores LDT register into the given memory area. * * @param Destination * Supplies a pointer to the memory area where LDT will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::StoreLocalDescriptorTable(OUT PVOID Destination) { __asm__ volatile("sldt %0" : "=m" (*(PSHORT)Destination) : : "memory"); } /** * Stores specified segment into the given memory area. * * @param Segment * Supplies a segment identification. * * @param Destination * Supplies a pointer to the memory area where segment data will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::StoreSegment(IN USHORT Segment, OUT PVOID Destination) { switch(Segment) { case SEGMENT_CS: __asm__ volatile("movl %%cs, %0" : "=r" (*(PUINT)Destination)); break; case SEGMENT_DS: __asm__ volatile("movl %%ds, %0" : "=r" (*(PUINT)Destination)); break; case SEGMENT_ES: __asm__ volatile("movl %%es, %0" : "=r" (*(PUINT)Destination)); break; case SEGMENT_FS: __asm__ volatile("movl %%fs, %0" : "=r" (*(PUINT)Destination)); break; case SEGMENT_GS: __asm__ volatile("movl %%gs, %0" : "=r" (*(PUINT)Destination)); break; case SEGMENT_SS: __asm__ volatile("movl %%ss, %0" : "=r" (*(PUINT)Destination)); break; default: Destination = NULLPTR; break; } } /** * Stores TR into the given memory area. * * @param Destination * Supplies a pointer to the memory area where TR will be stores. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::StoreTaskRegister(OUT PVOID Destination) { __asm__ volatile("str %0" : "=m" (*(PULONG)Destination) : : "memory"); } /** * Writes a value to the specified CPU control register. * * @param ControlRegister * Supplies a number of a control register which controls the general behavior of a CPU. * * @param Value * Suplies a value to write to the CR register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::WriteControlRegister(IN USHORT ControlRegister, IN UINT_PTR Value) { /* Write a value into specified control register */ switch(ControlRegister) { case 0: /* Write value to CR0 */ __asm__ volatile("mov %0, %%cr0" : : "r"(Value) : "memory"); break; case 2: /* Write value to CR2 */ __asm__ volatile("mov %0, %%cr2" : : "r"(Value) : "memory"); break; case 3: /* Write value to CR3 */ __asm__ volatile("mov %0, %%cr3" : : "r"(Value) : "memory"); break; case 4: /* Write value to CR4 */ __asm__ volatile("mov %0, %%cr4" : : "r"(Value) : "memory"); break; case 8: /* Write value to CR8 */ __asm__ volatile("mov %0, %%cr8" : : "r"(Value) : "memory"); break; } } /** * Writes a value to the specified CPU debug register. * * @param DebugRegister * Supplies a number of a debug register for write operation. * * @param Value * Suplies a value to write to the specified DR register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::WriteDebugRegister(IN USHORT DebugRegister, IN UINT_PTR Value) { /* Write a value into specified debug register */ switch(DebugRegister) { case 0: /* Write value to DR0 */ __asm__ volatile("mov %0, %%dr0" : : "r" (Value) : "memory"); break; case 1: /* Write value to DR1 */ __asm__ volatile("mov %0, %%dr1" : : "r" (Value) : "memory"); break; case 2: /* Write value to DR2 */ __asm__ volatile("mov %0, %%dr2" : : "r" (Value) : "memory"); break; case 3: /* Write value to DR3 */ __asm__ volatile("mov %0, %%dr3" : : "r" (Value) : "memory"); break; case 4: /* Write value to DR4 */ __asm__ volatile("mov %0, %%dr4" : : "r" (Value) : "memory"); break; case 5: /* Write value to DR5 */ __asm__ volatile("mov %0, %%dr5" : : "r" (Value) : "memory"); break; case 6: /* Write value to DR6 */ __asm__ volatile("mov %0, %%dr6" : : "r" (Value) : "memory"); break; case 7: /* Write value to DR7 */ __asm__ volatile("mov %0, %%dr7" : : "r" (Value) : "memory"); break; } } /** * Writes the specified value to the program status and control (EFLAGS) register. * * @param Value * The value to write to the EFLAGS register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::WriteEflagsRegister(IN UINT_PTR Value) { __asm__ volatile("push %0\n" "popf" : : "rim" (Value)); } /** * Writes a 64-bit value to the requested Model Specific Register (MSR). * * @param Register * Supplies the MSR register to write. * * @param Value * Supplies the 64-bit value to write. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::WriteModelSpecificRegister(IN ULONG Register, IN ULONGLONG Value) { ULONG Low = Value & 0xFFFFFFFF; ULONG High = Value >> 32; __asm__ volatile("wrmsr" : : "c" (Register), "a" (Low), "d" (High)); } /** * Yields a current thread running on the processor. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::YieldProcessor(VOID) { __asm__ volatile("pause" : : : "memory"); } ================================================ FILE: xtoskrnl/ar/amd64/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ar/amd64/data.cc * DESCRIPTION: AMD64 architecture-specific global and static data * DEVELOPERS: Rafal Kupiec */ #include /* Initial kernel boot stack */ UCHAR AR::ProcessorSupport::BootStack[KERNEL_STACK_SIZE] = {}; /* Initial kernel fault stack */ UCHAR AR::ProcessorSupport::FaultStack[KERNEL_STACK_SIZE] = {}; /* Initial GDT */ KGDTENTRY AR::ProcessorSupport::InitialGdt[GDT_ENTRIES] = {}; /* Initial IDT */ KIDTENTRY AR::ProcessorSupport::InitialIdt[IDT_ENTRIES] = {}; /* Initial Processor Block */ KPROCESSOR_BLOCK AR::ProcessorSupport::InitialProcessorBlock; /* Initial TSS */ KTSS AR::ProcessorSupport::InitialTss; /* Initial kernel NMI stack */ UCHAR AR::ProcessorSupport::NmiStack[KERNEL_STACK_SIZE] = {}; /* Unhandled interrupt routine */ PINTERRUPT_HANDLER AR::Traps::UnhandledInterruptRoutine = NULLPTR; ================================================ FILE: xtoskrnl/ar/amd64/procsup.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ar/amd64/procsup.cc * DESCRIPTION: AMD64 processor functionality support * DEVELOPERS: Rafal Kupiec */ #include /** * Gets the base address of the kernel boot stack. * * @return This routine returns a pointer to the kernel boot stack. * * @since XT 1.0 */ XTAPI PVOID AR::ProcessorSupport::GetBootStack(VOID) { /* Return base address of kernel boot stack */ return (PVOID)((ULONG_PTR)BootStack + KERNEL_STACK_SIZE); } XTAPI VOID AR::ProcessorSupport::GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType, OUT PVOID *TrampolineCode, OUT PULONG_PTR TrampolineSize) { /* Get trampoline information */ switch(TrampolineType) { case TrampolineApStartup: /* Get AP startup trampoline information */ *TrampolineCode = (PVOID)ArStartApplicationProcessor; *TrampolineSize = (ULONG_PTR)ArStartApplicationProcessorEnd - (ULONG_PTR)ArStartApplicationProcessor; break; case TrampolineEnableXpa: /* Get Enable XPA trampoline information */ *TrampolineCode = (PVOID)ArEnableExtendedPhysicalAddressing; *TrampolineSize = (ULONG_PTR)ArEnableExtendedPhysicalAddressingEnd - (ULONG_PTR)ArEnableExtendedPhysicalAddressing; break; default: /* Unknown trampoline type */ *TrampolineCode = NULLPTR; *TrampolineSize = 0; break; } } /** * Identifies processor type (vendor, model, stepping) as well as looks for available CPU features and stores them * in Processor Control Block (PRCB). * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::IdentifyProcessor(VOID) { PKPROCESSOR_CONTROL_BLOCK Prcb; CPUID_REGISTERS CpuRegisters; CPUID_SIGNATURE CpuSignature; /* Get current processor control block */ Prcb = KE::Processor::GetCurrentProcessorControlBlock(); /* Get CPU vendor by issueing CPUID instruction */ RtlZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_VENDOR_STRING; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU vendor in processor control block */ Prcb->CpuId.Vendor = (CPU_VENDOR)CpuRegisters.Ebx; *(PULONG)&Prcb->CpuId.VendorName[0] = CpuRegisters.Ebx; *(PULONG)&Prcb->CpuId.VendorName[4] = CpuRegisters.Edx; *(PULONG)&Prcb->CpuId.VendorName[8] = CpuRegisters.Ecx; Prcb->CpuId.VendorName[12] = '\0'; /* Get CPU standard features */ RtlZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU signature in processor control block */ CpuSignature = *(PCPUID_SIGNATURE)&CpuRegisters.Eax; Prcb->CpuId.Family = CpuSignature.Family; Prcb->CpuId.Model = CpuSignature.Model; Prcb->CpuId.Stepping = CpuSignature.Stepping; /* CPU vendor specific quirks */ if(Prcb->CpuId.Vendor == CPU_VENDOR_AMD) { /* AMD CPU */ if(CpuSignature.Family == 0xF) { Prcb->CpuId.Family += CpuSignature.ExtendedFamily; Prcb->CpuId.Model += (CpuSignature.ExtendedModel << 4); } } else if(Prcb->CpuId.Vendor == CPU_VENDOR_INTEL) { /* Intel CPU */ if(CpuSignature.Family == 0xF) { Prcb->CpuId.Family += CpuSignature.ExtendedFamily; } if((CpuSignature.Family == 0x6) || (CpuSignature.Family == 0xF)) { Prcb->CpuId.Model += (CpuSignature.ExtendedModel << 4); } } else { /* Unknown CPU vendor */ Prcb->CpuId.Vendor = CPU_VENDOR_UNKNOWN; } /* Identify processor features */ IdentifyProcessorFeatures(); } /** * Identifies processor features and stores them in Processor Control Block (PRCB). * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::IdentifyProcessorFeatures(VOID) { ULONG MaxExtendedLeaf, MaxStandardLeaf; PKPROCESSOR_CONTROL_BLOCK Prcb; CPUID_REGISTERS CpuRegisters; /* Get current processor control block */ Prcb = KE::Processor::GetCurrentProcessorControlBlock(); /* Get maximum CPUID standard leaf */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_VENDOR_STRING; AR::CpuFunctions::CpuId(&CpuRegisters); MaxStandardLeaf = CpuRegisters.Eax; /* Get maximum CPUID extended leaf */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_EXTENDED_MAX; AR::CpuFunctions::CpuId(&CpuRegisters); MaxExtendedLeaf = CpuRegisters.Eax; /* Check if CPU supports standard features leaf */ if(MaxStandardLeaf >= CPUID_GET_STANDARD1_FEATURES) { /* Get CPU standard features */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU standard features in processor control block */ if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_SSE3) Prcb->CpuId.FeatureBits |= KCF_SSE3; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_VMX) Prcb->CpuId.FeatureBits |= KCF_VMX; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_SSSE3) Prcb->CpuId.FeatureBits |= KCF_SSSE3; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_SSE4_1) Prcb->CpuId.FeatureBits |= KCF_SSE41; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_SSE4_2) Prcb->CpuId.FeatureBits |= KCF_SSE42; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_X2APIC) Prcb->CpuId.FeatureBits |= KCF_X2APIC; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_POPCNT) Prcb->CpuId.FeatureBits |= KCF_POPCNT; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_TSC_DEADLINE) Prcb->CpuId.FeatureBits |= KCF_TSC_DEADLINE; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_AES) Prcb->CpuId.FeatureBits |= KCF_AES; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_XSAVE) Prcb->CpuId.FeatureBits |= KCF_XSAVE; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_AVX) Prcb->CpuId.FeatureBits |= KCF_AVX; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_RDRAND) Prcb->CpuId.FeatureBits |= KCF_RDRAND; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_VME) Prcb->CpuId.FeatureBits |= KCF_VME; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PSE) Prcb->CpuId.FeatureBits |= KCF_LARGE_PAGE; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_TSC) Prcb->CpuId.FeatureBits |= KCF_RDTSC; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PAE) Prcb->CpuId.FeatureBits |= KCF_PAE; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_MCE) Prcb->CpuId.FeatureBits |= KCF_MCE; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_CX8) Prcb->CpuId.FeatureBits |= KCF_CMPXCHG8B; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_APIC) Prcb->CpuId.FeatureBits |= KCF_APIC; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_SEP) Prcb->CpuId.FeatureBits |= KCF_FAST_SYSCALL; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_MTRR) Prcb->CpuId.FeatureBits |= KCF_MTRR; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PGE) Prcb->CpuId.FeatureBits |= KCF_GLOBAL_PAGE; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_MCA) Prcb->CpuId.FeatureBits |= KCF_MCA; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_CMOV) Prcb->CpuId.FeatureBits |= KCF_CMOV; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PAT) Prcb->CpuId.FeatureBits |= KCF_PAT; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PSE36) Prcb->CpuId.FeatureBits |= KCF_PSE36; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_CLFLUSH) Prcb->CpuId.FeatureBits |= KCF_CLFLUSH; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_FXSR) Prcb->CpuId.FeatureBits |= KCF_FXSR; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_ACPI) Prcb->CpuId.FeatureBits |= KCF_ACPI; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_MMX) Prcb->CpuId.FeatureBits |= KCF_MMX; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_SSE) Prcb->CpuId.FeatureBits |= KCF_SSE; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_SSE2) Prcb->CpuId.FeatureBits |= KCF_SSE2; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_HTT) Prcb->CpuId.FeatureBits |= KCF_SMT; } /* Check if CPU supports standard7 features leaf */ if(MaxStandardLeaf >= CPUID_GET_STANDARD7_FEATURES) { /* Get CPU standard features */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_STANDARD7_FEATURES; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU standard7 features in processor control block */ if(CpuRegisters.Ebx & CPUID_FEATURES_EBX_FSGSBASE) Prcb->CpuId.FeatureBits |= KCF_FSGSBASE; if(CpuRegisters.Ebx & CPUID_FEATURES_EBX_AVX2) Prcb->CpuId.FeatureBits |= KCF_AVX2; if(CpuRegisters.Ebx & CPUID_FEATURES_EBX_SMEP) Prcb->CpuId.FeatureBits |= KCF_SMEP; if(CpuRegisters.Ebx & CPUID_FEATURES_EBX_RDSEED) Prcb->CpuId.FeatureBits |= KCF_RDSEED; if(CpuRegisters.Ebx & CPUID_FEATURES_EBX_SMAP) Prcb->CpuId.FeatureBits |= KCF_SMAP; if(CpuRegisters.Ebx & CPUID_FEATURES_EBX_SHA) Prcb->CpuId.FeatureBits |= KCF_SHA; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_LA57) Prcb->CpuId.FeatureBits |= KCF_LA57; } /* Check if CPU supports power management leaf */ if(MaxStandardLeaf >= CPUID_GET_POWER_MANAGEMENT) { /* Get CPU power management features */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_POWER_MANAGEMENT; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU power management features in processor control block */ if(CpuRegisters.Eax & CPUID_FEATURES_EAX_ARAT) Prcb->CpuId.FeatureBits |= KCF_ARAT; } /* Check if CPU supports extended features leaf */ if(MaxExtendedLeaf >= CPUID_GET_EXTENDED_FEATURES) { /* Get CPU extended features */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_EXTENDED_FEATURES; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU extended features in processor control block */ if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_SVM) Prcb->CpuId.ExtendedFeatureBits |= KCF_SVM; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_SSE4A) Prcb->CpuId.ExtendedFeatureBits |= KCF_SSE4A; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_FMA4) Prcb->CpuId.ExtendedFeatureBits |= KCF_FMA4; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_TOPOLOGY_EXTENSIONS) Prcb->CpuId.ExtendedFeatureBits |= KCF_TOPOEXT; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_SYSCALL_SYSRET) Prcb->CpuId.ExtendedFeatureBits |= KCF_SYSCALL; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_NX) Prcb->CpuId.ExtendedFeatureBits |= KCF_NX_BIT; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_RDTSCP) Prcb->CpuId.ExtendedFeatureBits |= KCF_RDTSCP; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_LONG_MODE) Prcb->CpuId.ExtendedFeatureBits |= KCF_64BIT; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_3DNOW_EXT) Prcb->CpuId.ExtendedFeatureBits |= KCF_3DNOW_EXT; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_3DNOW) Prcb->CpuId.ExtendedFeatureBits |= KCF_3DNOW; } /* Check if CPU supports advanced power management leaf */ if(MaxExtendedLeaf >= CPUID_GET_ADVANCED_POWER_MANAGEMENT) { /* Get CPU advanced power management features */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_ADVANCED_POWER_MANAGEMENT; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU advanced power management features in processor control block */ if(CpuRegisters.Edx & CPUID_FEATURES_EDX_TSCI) Prcb->CpuId.ExtendedFeatureBits |= KCF_INVARIANT_TSC; } } /** * Initializes the kernel's Global Descriptor Table (GDT). * * @param Gdt * Supplies a pointer to the GDT to use. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeGdt(IN PKPROCESSOR_BLOCK ProcessorBlock) { /* Initialize GDT entries */ SetGdtEntry(ProcessorBlock->GdtBase, KGDT_NULL, 0x0, 0x0, KGDT_TYPE_NONE, KGDT_DPL_SYSTEM, 1); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R0_CODE, 0x0, 0x0, KGDT_TYPE_CODE, KGDT_DPL_SYSTEM, 1); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R0_DATA, 0x0, 0x0, KGDT_TYPE_DATA, KGDT_DPL_SYSTEM, 1); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R3_CMCODE, 0x0, 0xFFFFFFFF, KGDT_TYPE_CODE, KGDT_DPL_USER, 2); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R3_DATA, 0x0, 0xFFFFFFFF, KGDT_TYPE_DATA, KGDT_DPL_USER, 2); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R3_CODE, 0x0, 0x0, KGDT_TYPE_CODE, KGDT_DPL_USER, 1); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_SYS_TSS, (ULONG_PTR)ProcessorBlock->TssBase, sizeof(KTSS) - 1, AMD64_TSS, KGDT_DPL_SYSTEM, 0); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R3_CMTEB, 0x0, 0x0FFF, KGDT_TYPE_DATA, KGDT_DPL_USER, 2); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R0_LDT, 0x0, 0xFFFFFFFF, KGDT_TYPE_CODE, KGDT_DPL_SYSTEM, 0); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_ALIAS, (ULONG_PTR)ProcessorBlock->GdtBase, (GDT_ENTRIES * sizeof(KGDTENTRY)) - 1, KGDT_TYPE_DATA, KGDT_DPL_SYSTEM, 0); } /** * Initializes the kernel's Interrupt Descriptor Table (IDT). * * @param ProcessorBlock * Supplies a pointer to the processor block to use. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeIdt(IN PKPROCESSOR_BLOCK ProcessorBlock) { UINT Vector; /* Fill in all vectors */ for(Vector = 0; Vector < IDT_ENTRIES; Vector++) { /* Set the IDT to handle unexpected interrupts */ SetIdtGate(ProcessorBlock->IdtBase, Vector, (PVOID)ArInterruptEntry[Vector], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE); } /* Setup IDT handlers for known interrupts and traps */ SetIdtGate(ProcessorBlock->IdtBase, 0x00, (PVOID)ArTrapEntry[0x00], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x01, (PVOID)ArTrapEntry[0x01], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x02, (PVOID)ArTrapEntry[0x02], KGDT_R0_CODE, KIDT_IST_NMI, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x03, (PVOID)ArTrapEntry[0x03], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x04, (PVOID)ArTrapEntry[0x04], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x05, (PVOID)ArTrapEntry[0x05], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x06, (PVOID)ArTrapEntry[0x06], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x07, (PVOID)ArTrapEntry[0x07], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x08, (PVOID)ArTrapEntry[0x08], KGDT_R0_CODE, KIDT_IST_PANIC, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x09, (PVOID)ArTrapEntry[0x09], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x0A, (PVOID)ArTrapEntry[0x0A], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x0B, (PVOID)ArTrapEntry[0x0B], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x0C, (PVOID)ArTrapEntry[0x0C], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x0D, (PVOID)ArTrapEntry[0x0D], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x0E, (PVOID)ArTrapEntry[0x0E], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x10, (PVOID)ArTrapEntry[0x10], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x11, (PVOID)ArTrapEntry[0x11], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x12, (PVOID)ArTrapEntry[0x12], KGDT_R0_CODE, KIDT_IST_MCA, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x13, (PVOID)ArTrapEntry[0x13], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x1F, (PVOID)ArTrapEntry[0x1F], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x2C, (PVOID)ArTrapEntry[0x2C], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x2D, (PVOID)ArTrapEntry[0x2D], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_TRAP_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x2F, (PVOID)ArTrapEntry[0x2F], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0xE1, (PVOID)ArInterruptEntry[0xE1], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE); } /** * Initializes AMD64 processor specific structures. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeProcessor(IN PVOID ProcessorStructures) { PVOID KernelBootStack, KernelFaultStack, KernelNmiStack; KDESCRIPTOR GdtDescriptor, IdtDescriptor; PKPROCESSOR_BLOCK ProcessorBlock; PKGDTENTRY Gdt; PKIDTENTRY Idt; PKTSS Tss; /* Check if processor structures buffer provided */ if(ProcessorStructures) { /* Assign CPU structures from provided buffer */ InitializeProcessorStructures(ProcessorStructures, &Gdt, &Tss, &ProcessorBlock, &KernelBootStack, &KernelFaultStack, &KernelNmiStack); /* Use global IDT */ Idt = InitialIdt; } else { /* Use initial structures */ Gdt = InitialGdt; Idt = InitialIdt; Tss = &InitialTss; KernelBootStack = (PVOID)((ULONG_PTR)&BootStack + KERNEL_STACK_SIZE); KernelFaultStack = (PVOID)((ULONG_PTR)&FaultStack + KERNEL_STACK_SIZE); KernelNmiStack = (PVOID)((ULONG_PTR)&NmiStack + KERNEL_STACK_SIZE); ProcessorBlock = &InitialProcessorBlock; } /* Initialize processor block */ InitializeProcessorBlock(ProcessorBlock, Gdt, Idt, Tss, KernelFaultStack); /* Initialize GDT, IDT and TSS */ InitializeGdt(ProcessorBlock); InitializeIdt(ProcessorBlock); InitializeTss(ProcessorBlock, KernelBootStack, KernelFaultStack, KernelNmiStack); /* Set GDT and IDT descriptors */ GdtDescriptor.Base = Gdt; GdtDescriptor.Limit = (GDT_ENTRIES * sizeof(KGDTENTRY)) - 1; IdtDescriptor.Base = Idt; IdtDescriptor.Limit = (IDT_ENTRIES * sizeof(KIDTENTRY)) - 1; /* Load GDT, IDT and TSS */ AR::CpuFunctions::LoadGlobalDescriptorTable(&GdtDescriptor.Limit); AR::CpuFunctions::LoadInterruptDescriptorTable(&IdtDescriptor.Limit); AR::CpuFunctions::LoadTaskRegister((UINT)KGDT_SYS_TSS); /* Initialize segment registers */ InitializeSegments(); /* Set GS base */ AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_GSBASE, (ULONGLONG)ProcessorBlock); AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_KERNEL_GSBASE, (ULONGLONG)ProcessorBlock); /* Initialize processor registers */ InitializeProcessorRegisters(); /* Identify processor */ IdentifyProcessor(); } /** * Initializes processor block. * * @param ProcessorBlock * Supplies a pointer to the processor block to initialize. * * @param Gdt * Supplies a pointer to the GDT for this processor block. * * @param Idt * Supplies a pointer to the IDT for this processor block. * * @param Tss * Supplies a pointer to the TSS for this processor block. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeProcessorBlock(OUT PKPROCESSOR_BLOCK ProcessorBlock, IN PKGDTENTRY Gdt, IN PKIDTENTRY Idt, IN PKTSS Tss, IN PVOID DpcStack) { /* Set processor block and processor control block */ ProcessorBlock->Self = ProcessorBlock; ProcessorBlock->CurrentPrcb = &ProcessorBlock->Prcb; /* Set GDT, IDT and TSS descriptors */ ProcessorBlock->GdtBase = (PKGDTENTRY)(PVOID)Gdt; ProcessorBlock->IdtBase = Idt; ProcessorBlock->TssBase = Tss; ProcessorBlock->Prcb.RspBase = Tss->Rsp0; /* Setup DPC stack */ ProcessorBlock->Prcb.DpcStack = DpcStack; /* Setup processor control block */ ProcessorBlock->Prcb.CpuNumber = ProcessorBlock->CpuNumber; ProcessorBlock->Prcb.SetMember = 1ULL << ProcessorBlock->CpuNumber; ProcessorBlock->Prcb.MultiThreadProcessorSet = 1ULL << ProcessorBlock->CpuNumber; /* Clear DR6 and DR7 registers */ ProcessorBlock->Prcb.ProcessorState.SpecialRegisters.KernelDr6 = 0; ProcessorBlock->Prcb.ProcessorState.SpecialRegisters.KernelDr7 = 0; /* Set process and thread information */ ProcessorBlock->Prcb.CurrentThread = &(KE::KThread::GetInitialThread())->ThreadControlBlock; ProcessorBlock->Prcb.CurrentThread->ApcState.Process = &(KE::KProcess::GetInitialProcess())->ProcessControlBlock; ProcessorBlock->Prcb.IdleThread = &(KE::KThread::GetInitialThread())->ThreadControlBlock; ProcessorBlock->Prcb.NextThread = NULLPTR; /* Set initial MXCSR register value */ ProcessorBlock->Prcb.MxCsr = INITIAL_MXCSR; /* Set initial runlevel */ ProcessorBlock->RunLevel = PASSIVE_LEVEL; } /** * Initializes processor registers and other boot structures. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeProcessorRegisters(VOID) { ULONGLONG PatAttributes; /* Enable FXSAVE restore */ AR::CpuFunctions::WriteControlRegister(4, AR::CpuFunctions::ReadControlRegister(4) | CR4_FXSR); /* Enable XMMI exceptions */ AR::CpuFunctions::WriteControlRegister(4, AR::CpuFunctions::ReadControlRegister(4) | CR4_XMMEXCPT); /* Set debugger extension */ AR::CpuFunctions::WriteControlRegister(4, AR::CpuFunctions::ReadControlRegister(4) | CR4_DE); /* Enable large pages */ AR::CpuFunctions::WriteControlRegister(4, AR::CpuFunctions::ReadControlRegister(4) | CR4_PSE); /* Enable write-protection */ AR::CpuFunctions::WriteControlRegister(0, AR::CpuFunctions::ReadControlRegister(0) | CR0_WP); /* Set alignment mask */ AR::CpuFunctions::WriteControlRegister(0, AR::CpuFunctions::ReadControlRegister(0) | CR0_AM); /* Disable FPU monitoring */ AR::CpuFunctions::WriteControlRegister(0, AR::CpuFunctions::ReadControlRegister(0) & ~CR0_MP); /* Disable x87 FPU exceptions */ AR::CpuFunctions::WriteControlRegister(0, AR::CpuFunctions::ReadControlRegister(0) & ~CR0_NE); /* Flush the TLB */ AR::CpuFunctions::FlushTlb(); /* Initialize system call MSRs */ AR::Traps::InitializeSystemCallMsrs(); /* Enable No-Execute (NXE) in EFER MSR */ AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_EFER, CpuFunctions::ReadModelSpecificRegister(X86_MSR_EFER) | X86_MSR_EFER_NXE); /* Initialize Page Attribute Table */ PatAttributes = (PAT_TYPE_WB << 0) | (PAT_TYPE_USWC << 8) | (PAT_TYPE_WEAK_UC << 16) | (PAT_TYPE_STRONG_UC << 24) | (PAT_TYPE_WB << 32) | (PAT_TYPE_USWC << 40) | (PAT_TYPE_WEAK_UC << 48) | (PAT_TYPE_STRONG_UC << 56); AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_PAT, PatAttributes); /* Initialize MXCSR register */ AR::CpuFunctions::LoadMxcsrRegister(INITIAL_MXCSR); } /** * Initializes i686 processor specific structures with provided memory buffer. * * @param ProcessorStructures * Supplies a pointer to the allocated buffer with processor structures. * * @param Gdt * Supplies a pointer to the GDT. * * @param Tss * Supplies a pointer to the TSS. * * @param ProcessorBlock * Supplies a pointer to the processor block. * * @param KernelBootStack * Supplies a pointer to the kernel boot stack. * * @param KernelFaultStack * Supplies a pointer to the kernel fault stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeProcessorStructures(IN PVOID ProcessorStructures, OUT PKGDTENTRY *Gdt, OUT PKTSS *Tss, OUT PKPROCESSOR_BLOCK *ProcessorBlock, OUT PVOID *KernelBootStack, OUT PVOID *KernelFaultStack, OUT PVOID *KernelNmiStack) { UINT_PTR Address; /* Align address to page size boundary and move to kernel boot stack */ Address = ROUND_UP((UINT_PTR)ProcessorStructures, MM_PAGE_SIZE) + KERNEL_STACK_SIZE; /* Assign a space for kernel boot stack and advance */ if(KernelBootStack != NULLPTR) { /* Return kernel boot stack address */ *KernelBootStack = (PVOID)Address; } Address += KERNEL_STACK_SIZE; /* Assign a space for kernel fault stack and advance */ if(KernelFaultStack != NULLPTR) { /* Return kernel fault stack address */ *KernelFaultStack = (PVOID)Address; } Address += KERNEL_STACK_SIZE; /* Assign a space for kernel NMI stack, no advance needed as stack grows down */ if(KernelNmiStack != NULLPTR) { /* Return kernel NMI stack address */ *KernelNmiStack = (PVOID)Address; } /* Assign a space for GDT and advance */ if(Gdt != NULLPTR) { /* Return GDT base address */ *Gdt = (PKGDTENTRY)(PVOID)Address; } Address += (GDT_ENTRIES * sizeof(KGDTENTRY)); /* Assign a space for TSS and advance */ if(Tss != NULLPTR) { *Tss = (PKTSS)(PVOID)Address; } Address += sizeof(KTSS); /* Assign a space for Processor Block and advance */ if(ProcessorBlock != NULLPTR) { /* Return processor block address */ *ProcessorBlock = (PKPROCESSOR_BLOCK)(PVOID)Address; } } /** * Initializes segment registers. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeSegments(VOID) { /* Initialize segments */ AR::CpuFunctions::LoadSegment(SEGMENT_CS, KGDT_R0_CODE); AR::CpuFunctions::LoadSegment(SEGMENT_DS, KGDT_R3_DATA | RPL_MASK); AR::CpuFunctions::LoadSegment(SEGMENT_ES, KGDT_R3_DATA | RPL_MASK); AR::CpuFunctions::LoadSegment(SEGMENT_FS, KGDT_R3_CMTEB | RPL_MASK); AR::CpuFunctions::LoadSegment(SEGMENT_GS, KGDT_R3_DATA | RPL_MASK); AR::CpuFunctions::LoadSegment(SEGMENT_SS, KGDT_R0_DATA); } /** * Initializes the kernel's Task State Segment (TSS). * * @param Tss * Supplies a pointer to the TSS to use. * * @param Gdt * Supplies a pointer to the GDT to use. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeTss(IN PKPROCESSOR_BLOCK ProcessorBlock, IN PVOID KernelBootStack, IN PVOID KernelFaultStack, IN PVOID KernelNmiStack) { /* Fill TSS with zeroes */ RtlZeroMemory(ProcessorBlock->TssBase, sizeof(KTSS)); /* Setup I/O map and stacks for ring0 & traps */ ProcessorBlock->TssBase->IoMapBase = sizeof(KTSS); ProcessorBlock->TssBase->Rsp0 = (ULONG_PTR)KernelBootStack; ProcessorBlock->TssBase->Ist[KIDT_IST_PANIC] = (ULONG_PTR)KernelFaultStack; ProcessorBlock->TssBase->Ist[KIDT_IST_MCA] = (ULONG_PTR)KernelFaultStack; ProcessorBlock->TssBase->Ist[KIDT_IST_NMI] = (ULONG_PTR)KernelNmiStack; } /** * Fills in an AMD64 GDT entry. * * @param Gdt * Supplies a pointer to the GDT. * * @param Selector * Specifies a segment selector of the GDT entry. * * @param Base * Specifies a base address value of the descriptor. * * @param Limit * Specifies a descriptor limit. * * @param Type * Specifies a type of the descriptor. * * @param Dpl * Specifies the descriptor privilege level. * * @param SegmentMode * Specifies a segment mode of the descriptor. * * @return This routine does not return any value * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::SetGdtEntry(IN PKGDTENTRY Gdt, IN USHORT Selector, IN ULONG_PTR Base, IN ULONG Limit, IN UCHAR Type, IN UCHAR Dpl, IN UCHAR SegmentMode) { PKGDTENTRY GdtEntry; UCHAR Granularity; /* Set the granularity flag depending on descriptor limit */ if(Limit < 0x100000) { /* Limit is in 1B blocks */ Granularity = 0; } else { /* Limit is in 4KB blocks */ Granularity = 1; Limit >>= 12; } /* Get GDT entry */ GdtEntry = (PKGDTENTRY)((ULONG_PTR)Gdt + (Selector & ~RPL_MASK)); /* Set GDT descriptor base */ GdtEntry->BaseLow = (Base & 0xFFFF); GdtEntry->Bytes.BaseMiddle = ((Base >> 16) & 0xFF); GdtEntry->Bytes.BaseHigh = ((Base >> 24) & 0xFF); GdtEntry->BaseUpper = (Base >> 32); /* Set descriptor limit */ GdtEntry->LimitLow = (Limit & 0xFFFF); GdtEntry->Bits.LimitHigh = ((Limit >> 16) & 0xF); /* Initialize GDT entry */ GdtEntry->Bits.DefaultBig = !!(SegmentMode & 2); GdtEntry->Bits.Dpl = (Dpl & 0x3); GdtEntry->Bits.Granularity = Granularity; GdtEntry->Bits.LongMode = !!(SegmentMode & 1); GdtEntry->Bits.Present = (Type != 0); GdtEntry->Bits.System = 0; GdtEntry->Bits.Type = (Type & 0x1F); GdtEntry->MustBeZero = 0; } /** * Updates an existing AMD64 GDT entry with new base address. * * @param Gdt * Supplies a pointer to the GDT. * * @param Selector * Specifies a segment selector of the GDT entry. * * @param Base * Specifies a base address value of the descriptor. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::SetGdtEntryBase(IN PKGDTENTRY Gdt, IN USHORT Selector, IN ULONG_PTR Base) { PKGDTENTRY GdtEntry; /* Get GDT entry */ GdtEntry = (PKGDTENTRY)((ULONG_PTR)Gdt + (Selector & ~RPL_MASK)); /* Set new GDT descriptor base */ GdtEntry->BaseLow = (Base & 0xFFFF); GdtEntry->Bytes.BaseMiddle = ((Base >> 16) & 0xFF); GdtEntry->Bytes.BaseHigh = ((Base >> 24) & 0xFF); GdtEntry->BaseUpper = (Base >> 32); } /** * Fills in a call, interrupt, task or trap gate entry. * * @param Idt * Supplies a pointer to IDT structure, where gate is located. * * @param Vector * Supplies a gate vector pointing to the interrupt gate in the IDT * * @param Handler * Supplies a pointer to the interrupt handler of the specified gate. * * @param Selector * Supplies the code selector the gate should run in. * * @param Ist * Supplies the interrupt stack table entry the gate should run in. * * @param Access * Supplies the gate access rights. * * @param Type * Supplies the gate type. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::SetIdtGate(IN PKIDTENTRY Idt, IN USHORT Vector, IN PVOID Handler, IN USHORT Selector, IN USHORT Ist, IN USHORT Dpl, IN USHORT Type) { /* Set the handler's address */ Idt[Vector].OffsetLow = ((ULONG_PTR)Handler & 0xFFFF); Idt[Vector].OffsetMiddle = (((ULONG_PTR)Handler >> 16) & 0xFFFF); Idt[Vector].OffsetHigh = (ULONG_PTR)Handler >> 32; /* Set the code segment selector */ Idt[Vector].Selector = Selector; /* Initialize the gate's attributes and flags */ Idt[Vector].Access = 0; Idt[Vector].Dpl = Dpl; Idt[Vector].IstIndex = Ist; Idt[Vector].Present = 1; Idt[Vector].Reserved1 = 0; Idt[Vector].Type = Type; } ================================================ FILE: xtoskrnl/ar/amd64/traps.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ar/amd64/traps.cc * DESCRIPTION: AMD64 system traps * DEVELOPERS: Rafal Kupiec */ #include /** * Dispatches the interrupt provided by common interrupt handler. * * @param TrapFrame * Supplies a kernel trap frame pushed by common interrupt handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::DispatchInterrupt(IN PKTRAP_FRAME TrapFrame) { PINTERRUPT_HANDLER Handler; /* Read the handler pointer from the CPU's interrupt dispatch table */ Handler = (PINTERRUPT_HANDLER)AR::CpuFunctions::ReadGSQuadWord(FIELD_OFFSET(KPROCESSOR_BLOCK, InterruptDispatchTable) + (TrapFrame->Vector * sizeof(PINTERRUPT_HANDLER))); /* Check if the interrupt has a handler registered */ if(Handler != NULLPTR) { /* Call the handler */ Handler(TrapFrame); } else if(UnhandledInterruptRoutine != NULLPTR) { /* Call the unhandled interrupt routine */ UnhandledInterruptRoutine(TrapFrame); } else { /* Dispatcher not initialized, print a debug message */ DebugPrint(L"ERROR: Caught unhandled interrupt: 0x%.2llX\n", TrapFrame->Vector); } } /** * Dispatches the trap provided by common trap handler. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::DispatchTrap(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Caught trap: 0x%.2llX with error code: %.4llX at RIP: 0x%.16llX\n" L"RAX: 0x%.16llX, RBX: 0x%.16llX, RCX: 0x%.16llX, RDX: 0x%.16llX\n" L"R8: 0x%.16llX, R9: 0x%.16llX, R10: 0x%.16llX, R11: 0x%.16llX\n" L"R12: 0x%.16llX, R13: 0x%.16llX, R14: 0x%.16llX, R15: 0x%.16llX\n" L"RBP: 0x%.16llX, RSP: 0x%.16llX, RDI: 0x%.16llX, RSI: 0x%.16llX\n" L"DR0: 0x%.16llX, DR1: 0x%.16llX, DR2: 0x%.16llX, DR3: 0x%.16llX\n" L"DR6: 0x%.16llX, DR7: 0x%.16llX\n" L"CR2: 0x%.16llX, CR3: 0x%.16llX, CS: 0x%.16llX, DS: 0x%.16hX\n" L"ES: 0x%.16hX, FS: 0x%.16hX, GS: 0x%.16hX, SS: 0x%.16llX\n", TrapFrame->Vector, TrapFrame->ErrorCode, TrapFrame->Rip, TrapFrame->Rax, TrapFrame->Rbx, TrapFrame->Rcx, TrapFrame->Rdx, TrapFrame->R8, TrapFrame->R9, TrapFrame->R10, TrapFrame->R11, TrapFrame->R12, TrapFrame->R13, TrapFrame->R14, TrapFrame->R15, TrapFrame->Rbp, TrapFrame->Rsp, TrapFrame->Rdi, TrapFrame->Rsi, TrapFrame->Dr0, TrapFrame->Dr1, TrapFrame->Dr2, TrapFrame->Dr3, TrapFrame->Dr6, TrapFrame->Dr7, TrapFrame->Cr2, TrapFrame->Cr3, TrapFrame->SegCs, TrapFrame->SegDs, TrapFrame->SegEs, TrapFrame->SegFs, TrapFrame->SegGs, TrapFrame->SegSs); /* Check vector and call appropriate handler */ switch(TrapFrame->Vector) { case 0x00: /* Divide By Zero exception */ HandleTrap00(TrapFrame); break; case 0x01: /* Debug exception */ HandleTrap01(TrapFrame); break; case 0x02: /* Non-Maskable Interrupt (NMI) */ HandleTrap02(TrapFrame); break; case 0x03: /* INT3 instruction executed */ HandleTrap03(TrapFrame); break; case 0x04: /* Overflow exception */ HandleTrap04(TrapFrame); break; case 0x05: /* Bound Range Exceeded exception */ HandleTrap05(TrapFrame); break; case 0x06: /* Invalid Opcode exception */ HandleTrap06(TrapFrame); break; case 0x07: /* Device Not Available exception */ HandleTrap07(TrapFrame); break; case 0x08: /* Double Fault exception */ HandleTrap08(TrapFrame); break; case 0x09: /* Segment Overrun exception */ HandleTrap09(TrapFrame); break; case 0x0A: /* Invalid TSS exception */ HandleTrap0A(TrapFrame); break; case 0x0B: /* Segment Not Present exception */ HandleTrap0B(TrapFrame); break; case 0x0C: /* Stack Segment Fault exception */ HandleTrap0C(TrapFrame); break; case 0x0D: /* General Protection Fault (GPF) exception*/ HandleTrap0D(TrapFrame); break; case 0x0E: /* Page Fault exception */ HandleTrap0E(TrapFrame); break; case 0x10: /* X87 Floating-Point exception */ HandleTrap10(TrapFrame); break; case 0x11: /* Alignment Check exception */ HandleTrap11(TrapFrame); break; case 0x12: /* Machine Check exception */ HandleTrap12(TrapFrame); break; case 0x13: /* SIMD Floating-Point exception */ HandleTrap13(TrapFrame); break; case 0x1F: /* Software Interrupt at APC level */ HandleTrap1F(TrapFrame); break; case 0x2C: /* Assertion raised */ HandleTrap2C(TrapFrame); break; case 0x2D: /* Debug-Service-Request raised */ HandleTrap2D(TrapFrame); break; case 0x2F: /* Software Interrupt at DISPATCH level */ HandleTrap2F(TrapFrame); break; case 0xE1: /* InterProcessor Interrupt (IPI) */ HandleTrapE1(TrapFrame); break; default: /* Unknown/Unexpected trap */ HandleTrapFF(TrapFrame); break; } } /** * Handles a 32-bit system call. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleSystemCall32(VOID) { DebugPrint(L"Handled 32-bit system call!\n"); } /** * Handles a 64-bit system call. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleSystemCall64(VOID) { DebugPrint(L"Handled 64-bit system call!\n"); } /** * Handles the trap 0x00 when a Divide By Zero exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap00(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Division-By-Zero Error (0x00)!\n"); KE::Crash::Panic(0x00); } /** * Handles the trap 0x01 when Debug exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap01(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Debug exception (0x01)!\n"); KE::Crash::Panic(0x01); } /** * Handles the trap 0x02 when Non-Maskable Interrupt (NMI) occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap02(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Non-Maskable-Interrupt (0x02)!\n"); } /** * Handles the trap 0x03 when the INT3 instruction is executed. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap03(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled INT3 (0x03)!\n"); KE::Crash::Panic(0x03); } /** * Handles the trap 0x04 when the INTO instruction is executed and overflow bit is set. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap04(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Overflow exception (0x04)!\n"); KE::Crash::Panic(0x04); } /** * Handles the trap 0x05 when the Bound Range Exceeded exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap05(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Bound-Range-Exceeded exception (0x05)!\n"); KE::Crash::Panic(0x05); } /** * Handles the trap 0x06 when the Invalid Opcode exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap06(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Invalid Opcode exception (0x06)!\n"); KE::Crash::Panic(0x06); } /** * Handles the trap 0x07 when the Device Not Available exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap07(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Device Not Available exception (0x07)!\n"); KE::Crash::Panic(0x07); } /** * Handles the trap 0x08 when Double Fault exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap08(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Double-Fault exception (0x08)!\n"); KE::Crash::Panic(0x08); } /** * Handles the trap 0x09 when the Segment Overrun exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap09(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Segment-Overrun exception (0x09)!\n"); KE::Crash::Panic(0x09); } /** * Handles the trap 0x0A when the Invalid TSS exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap0A(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Invalid-TSS exception (0x0A)!\n"); KE::Crash::Panic(0x0A); } /** * Handles the trap 0x0B when the Segment Not Present exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap0B(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Segment-Not-Present exception (0x0B)!\n"); KE::Crash::Panic(0x0B); } /** * Handles the trap 0x0C when the Stack Segment Fault exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap0C(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Stack-Segment-Fault exception (0x0C)!\n"); KE::Crash::Panic(0x0C); } /** * Handles the trap 0x0D when General Protection Fault (GPF) exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap0D(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled General-Protection-Fault (0x0D)!\n"); KE::Crash::Panic(0x0D); } /** * Handles the trap 0x0E when the Page Fault (PF) exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap0E(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Page-Fault exception (0x0E)!\n"); KE::Crash::Panic(0x0E); } /** * Handles the trap 0x10 when the X87 Floating-Point exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap10(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled x87 Floating-Point exception (0x10)!\n"); KE::Crash::Panic(0x10); } /** * Handles the trap 0x11 when the Alignment Check exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap11(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Alignment-Check exception (0x11)!\n"); KE::Crash::Panic(0x11); } /** * Handles the trap 0x12 when the Machine Check exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap12(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Machine-Check exception (0x12)!\n"); KE::Crash::Panic(0x12); } /** * Handles the trap 0x13 when the SIMD Floating-Point exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap13(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled SIMD Floating-Point exception (0x13)!\n"); KE::Crash::Panic(0x13); } /** * Handles the trap 0x1F when software interrupt gets generated at APC_LEVEL. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap1F(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Unhandled software interrupt at APC level (0x1F)!\n"); } /** * Handles the trap 0x2C when an assertion is raised. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap2C(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Assertion (0x2C)!\n"); KE::Crash::Panic(0x2C); } /** * Handles the trap 0x2D when a debug service is being requested. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap2D(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Debug-Service-Request (0x2D)!\n"); KE::Crash::Panic(0x2D); } /** * Handles the trap 0x2F when a software interrupt gets generated at DISPATCH_LEVEL. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap2F(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Unhandled software interrupt at DISPATCH level (0x2F)!\n"); } /** * Handles the trap 0xE1 when InterProcessor Interrupt (IPI) occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrapE1(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Unhandled IPI interrupt (0xE1)!\n"); } /** * Handles the trap 0xFF when Unexpected Interrupt occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrapFF(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Unexpected-Interrupt (0xFF)!\n"); KE::Crash::Panic(0xFF); } /** * Initializes system call MSRs. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::InitializeSystemCallMsrs(VOID) { /* Initialize system calls MSR */ CpuFunctions::WriteModelSpecificRegister(X86_MSR_STAR, (((ULONG64)KGDT_R3_CMCODE | RPL_MASK) << 48) | ((ULONG64)KGDT_R0_CODE << 32)); CpuFunctions::WriteModelSpecificRegister(X86_MSR_CSTAR, (ULONG64)&HandleSystemCall32); CpuFunctions::WriteModelSpecificRegister(X86_MSR_LSTAR, (ULONG64)&HandleSystemCall64); CpuFunctions::WriteModelSpecificRegister(X86_MSR_FMASK, X86_EFLAGS_IF_MASK | X86_EFLAGS_TF_MASK); /* Enable system call extensions (SCE) in EFER MSR */ CpuFunctions::WriteModelSpecificRegister(X86_MSR_EFER, CpuFunctions::ReadModelSpecificRegister(X86_MSR_EFER) | X86_MSR_EFER_SCE); } /** * Sets the unhandled interrupt routine used for vectors that have no handler registered. * * @param Handler * Supplies the pointer to the interrupt handler routine. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::Traps::SetUnhandledInterruptRoutine(PINTERRUPT_HANDLER Handler) { /* Set the unhandled interrupt routine */ UnhandledInterruptRoutine = Handler; } ================================================ FILE: xtoskrnl/ar/i686/archsup.S ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ar/i686/archsup.S * DESCRIPTION: Provides i686 architecture features not implementable in C. * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include #include .altmacro .text /** * Creates a task, trap or interrupt handler for the specified vector. * * @param Vector * Supplies a vector number. * * @param Type * Specifies whether the handler is designed to handle an interrupt, a task or a trap. * * @return This macro does not return any value. * * @since XT 1.0 */ .macro ArCreateHandler Vector Type .global _Ar\Type\Vector _Ar\Type\Vector: /* Check handler type */ .ifc \Type,Task _Ar\Type\Vector\()Start: /* Clear the Task Switch flag */ clts /* Allocate the trap frame and inject the hardware vector for the dispatcher */ sub $KTRAP_FRAME_SIZE, %esp movl $\Vector, KTRAP_FRAME_Vector(%esp) /* Pass the trap frame pointer as an argument and clear the direction flag */ push %esp cld /* Pass control to the trap dispatcher */ call _ArDispatchTrap /* Discard the argument and deallocate the trap frame */ add $4, %esp add $KTRAP_FRAME_SIZE, %esp /* Hardware task return */ iretl /* Spin back to the entry point to rearm the task gate */ jmp _Ar\Type\Vector\()Start .else /* Check handler type */ .ifc \Type,Trap /* Push fake error code for non-error vector traps */ .if \Vector != 8 && \Vector != 10 && \Vector != 11 && \Vector != 12 && \Vector != 13 && \Vector != 14 && \Vector != 17 && \Vector != 30 push $0 .endif .else /* Push fake error code for interrupts */ push $0 .endif /* Push vector number */ push $\Vector /* Push General Purpose Registers */ push %ebp push %edi push %esi push %edx push %ecx push %ebx push %eax /* Reserve space for other registers and point RBP to the trap frame */ sub $(KTRAP_FRAME_SIZE - KTRAP_FRAME_REGISTERS_SIZE), %esp lea (%esp), %ebp /* Store segment selectors */ mov %gs, KTRAP_FRAME_SegGs(%ebp) mov %fs, KTRAP_FRAME_SegFs(%ebp) mov %es, KTRAP_FRAME_SegEs(%ebp) mov %ds, KTRAP_FRAME_SegDs(%ebp) /* Store debug registers */ mov %dr7, %eax mov %eax, KTRAP_FRAME_Dr7(%ebp) mov %dr6, %eax mov %eax, KTRAP_FRAME_Dr6(%ebp) mov %dr3, %eax mov %eax, KTRAP_FRAME_Dr3(%ebp) mov %dr2, %eax mov %eax, KTRAP_FRAME_Dr2(%ebp) mov %dr1, %eax mov %eax, KTRAP_FRAME_Dr1(%ebp) mov %dr0, %eax mov %eax, KTRAP_FRAME_Dr0(%ebp) /* Store CR2 and CR3 */ mov %cr3, %eax mov %eax, KTRAP_FRAME_Cr3(%ebp) mov %cr2, %eax mov %eax, KTRAP_FRAME_Cr2(%ebp) /* Test previous mode */ movl $0, KTRAP_FRAME_PreviousMode(%ebp) mov KTRAP_FRAME_SegCs(%ebp), %ax and $3, %al mov %al, KTRAP_FRAME_PreviousMode(%ebp) jz Dispatch\Type\Vector /* Load Kernel PB selector into FS */ mov $KGDT_R0_PB, %ax mov %ax, %fs /* Set sane data segment selectors */ mov $(KGDT_R3_DATA | RPL_MASK), %ax mov %ax, %ds mov %ax, %es Dispatch\Type\Vector: /* Push Frame Pointer and clear direction flag */ push %esp cld .ifc \Type,Trap /* Pass to the trap dispatcher */ call _ArDispatchTrap .else /* Pass to the interrupt dispatcher */ call _ArDispatchInterrupt .endif /* Clean up the stack */ add $4, %esp /* Test previous mode and disable interrupts before user mode return */ testb $1, KTRAP_FRAME_PreviousMode(%ebp) jz RestoreState\Type\Vector cli RestoreState\Type\Vector: /* Restore segment selectors */ mov KTRAP_FRAME_SegDs(%ebp), %ds mov KTRAP_FRAME_SegEs(%ebp), %es mov KTRAP_FRAME_SegFs(%ebp), %fs mov KTRAP_FRAME_SegGs(%ebp), %gs /* Free stack space */ add $(KTRAP_FRAME_SIZE - KTRAP_FRAME_REGISTERS_SIZE), %esp /* Pop General Purpose Registers */ pop %eax pop %ebx pop %ecx pop %edx pop %esi pop %edi pop %ebp /* Skip error code and vector number, then return */ add $(2 * 4), %esp iretl .endif .endm /* Populate common interrupt, task and trap handlers */ .irp i,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F .irp j,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F ArCreateHandler 0x\i\j Interrupt .if 0x\i\j == 0x02 || 0x\i\j == 0x08 ArCreateHandler 0x\i\j Task .else ArCreateHandler 0x\i\j Trap .endif .endr .endr /* Define array of pointers to the interrupt handlers */ .global _ArInterruptEntry _ArInterruptEntry: .irp i,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F .irp j,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F .long _ArInterrupt0x\i\j .endr .endr /* Define array of pointers to the trap handlers */ .global _ArTrapEntry _ArTrapEntry: .irp i,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F .irp j,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F .if 0x\i\j == 0x02 || 0x\i\j == 0x08 .long _ArTask0x\i\j .else .long _ArTrap0x\i\j .endif .endr .endr /** * Enables eXtended Physical Addressing (XPA). On i386, this is just a stub. * * @param PageMap * Supplies a pointer to the page map to be used. * * @return This routine does not return any value. * * @since XT 1.0 */ .global ArEnableExtendedPhysicalAddressing ArEnableExtendedPhysicalAddressing: .global ArEnableExtendedPhysicalAddressingEnd ArEnableExtendedPhysicalAddressingEnd: /** * Handles a spurious interrupt allowing it to end up. * * @return This routine does not return any value. * * @since XT 1.0 */ .global _ArHandleSpuriousInterrupt _ArHandleSpuriousInterrupt: iret /** * Starts an application processor (AP). * * @return This routine does not return any value. * * @since XT 1.0 */ .global _ArStartApplicationProcessor _ArStartApplicationProcessor: /* Enter 16-bit real mode */ .code16 /* Disable interrupts and clear direction flag */ cli cld /* Establish a flat addressing baseline */ movw %cs, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss /* Calculate absolute physical base address */ xorl %ebx, %ebx movw %cs, %bx shll $4, %ebx /* Set up a temporary stack for the AP initialization */ movl %ebx, %esp addl $0x1000, %esp /* Load the temporary Global Descriptor Table */ leal (ApTemporaryGdtDesc - _ArStartApplicationProcessor)(%ebx), %eax movl %eax, (ApTemporaryGdtBase - _ArStartApplicationProcessor) lgdtl (ApTemporaryGdtSize - _ArStartApplicationProcessor) /* Enable Protected Mode */ movl %cr0, %eax orl $0x01, %eax movl %eax, %cr0 /* Far return to enter 32-bit protected mode */ leal (ApEnterProtectedMode - _ArStartApplicationProcessor)(%ebx), %eax pushl $KGDT_R0_CODE pushl %eax lretl ApEnterProtectedMode: /* Enter 32-bit protected mode */ .code32 /* Setup all data segment registers */ movw $KGDT_R0_DATA, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss xorw %ax, %ax movw %ax, %fs movw %ax, %gs /* Locate PROCESSOR_START_BLOCK structure */ leal (_ArStartApplicationProcessorEnd - _ArStartApplicationProcessor)(%ebx), %edi /* Load CR4 from BSP, but mask PCIDE and PGE */ movl PROCESSOR_START_BLOCK_Cr4(%edi), %eax andl $~(CR4_PGE | CR4_PCIDE), %eax movl %eax, %cr4 /* Load the Kernel Page Directory Base from BSP */ movl PROCESSOR_START_BLOCK_Cr3(%edi), %eax movl %eax, %cr3 /* Enable Paging */ movl %cr0, %eax orl $CR0_PG, %eax movl %eax, %cr0 /* Load dedicated Stack for AP */ movl PROCESSOR_START_BLOCK_Stack(%edi), %esp /* Save the pointer to PROCESSOR_START_BLOCK */ movl %edi, %ecx pushl %edi /* Call the EntryPoint routine */ movl PROCESSOR_START_BLOCK_EntryPoint(%edi), %eax call *%eax /* Fire the breakpoint and halt if the entry point returns */ .ApNoReturnPoint: int $0x03 hlt jmp .ApNoReturnPoint /* Data section for temporary GDT */ .align 8 ApTemporaryGdtSize: .short _ArStartApplicationProcessorEnd - ApTemporaryGdtDesc - 1 ApTemporaryGdtBase: .long 0x00000000 ApTemporaryGdtDesc: .quad 0x0000000000000000, 0x00CF9A000000FFFF, 0x00CF92000000FFFF .global _ArStartApplicationProcessorEnd _ArStartApplicationProcessorEnd: ================================================ FILE: xtoskrnl/ar/i686/cpufunc.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ar/i686/cpufunc.cc * DESCRIPTION: Routines to provide access to special i686 CPU instructions * DEVELOPERS: Rafal Kupiec */ #include /** * Instructs the processor to clear the interrupt flag. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::ClearInterruptFlag(VOID) { __asm__ volatile("cli"); } /** * Retrieves a various amount of information about the CPU. * * @param Registers * Supplies a pointer to the structure containing all the necessary registers and leafs for CPUID. * * @return This routine returns TRUE if CPUID function could be executed, FALSE otherwise. * * @since XT 1.0 */ XTCDECL BOOLEAN AR::CpuFunctions::CpuId(IN OUT PCPUID_REGISTERS Registers) { UINT32 MaxLeaf; /* Get highest function ID available */ __asm__ volatile("cpuid" : "=a" (MaxLeaf) : "a" (Registers->Leaf & 0x80000000) : "rbx", "rcx", "rdx"); /* Check if CPU supports this command */ if(Registers->Leaf > MaxLeaf) { /* Cannot call it, return FALSE */ return FALSE; } /* Execute CPUID function */ __asm__ volatile("cpuid" : "=a" (Registers->Eax), "=b" (Registers->Ebx), "=c" (Registers->Ecx), "=d" (Registers->Edx) : "a" (Registers->Leaf), "c" (Registers->SubLeaf)); /* Return TRUE */ return TRUE; } /** * Partially flushes the Translation Lookaside Buffer (TLB) * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::FlushTlb(VOID) { /* Flush the TLB by resetting the CR3 */ WriteControlRegister(3, ReadControlRegister(3)); } /** * Gets the EFLAGS register. * * @return This routine returns the EFLAGS register. * * @since XT 1.0 */ XTCDECL ULONG AR::CpuFunctions::GetCpuFlags(VOID) { ULONG_PTR Flags; /* Get EFLAGS register */ __asm__ volatile("pushf\n" "pop %0\n" : "=rm" (Flags) : : "memory"); /* Return flags */ return Flags; } /** * Gets the address of the current stack register. * * @return This routine returns the current stack pointer. * * @since XT 1.0 */ XTASSEMBLY XTCDECL ULONG_PTR AR::CpuFunctions::GetStackPointer(VOID) { /* Get current stack pointer */ __asm__ volatile("mov %%esp, %%eax\n" "ret\n" : : :); } /** * Halts the central processing unit (CPU). * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::Halt(VOID) { __asm__ volatile("hlt"); } /** * Checks whether interrupts are enabled or not. * * @return This routine returns TRUE if interrupts are enabled, or FALSE otherwise. * * @since XT 1.0 */ XTCDECL BOOLEAN AR::CpuFunctions::InterruptsEnabled(VOID) { ULONG_PTR Flags; /* Get RFLAGS register */ Flags = GetCpuFlags(); /* Check if interrupts are enabled and return result */ return (Flags & X86_EFLAGS_IF_MASK) ? TRUE : FALSE; } /** * Invalidates the TLB (Translation Lookaside Buffer) for specified virtual address. * * @param Address * Suuplies a virtual address whose associated TLB entry will be invalidated. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::InvalidateTlbEntry(PVOID Address) { __asm__ volatile("invlpg (%0)" : : "b" (Address) : "memory"); } /** * Loads the value in the source operand into the global descriptor table register (GDTR). * * @param Source * Specifies a memory location that contains the base address of GDT. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::LoadGlobalDescriptorTable(IN PVOID Source) { __asm__ volatile("lgdt %0" : : "m" (*(PSHORT)Source) : "memory"); } /** * Loads the value in the source operand into the interrupt descriptor table register (IDTR). * * @param Source * Specifies a memory location that contains the base address of IDT. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::LoadInterruptDescriptorTable(IN PVOID Source) { __asm__ volatile("lidt %0" : : "m" (*(PSHORT)Source) : "memory"); } /** * Loads the value in the source operand into the local descriptor table register (LDTR). * * @param Source * Specifies a selector value. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::LoadLocalDescriptorTable(IN USHORT Source) { __asm__ volatile("lldtw %0" : : "g" (Source)); } /** * Loads source data into specified segment. * * @param Segment * Supplies a segment identification. * * @param Source * Supplies a pointer to the memory area containing data that will be loaded into specified segment. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::LoadSegment(IN USHORT Segment, IN ULONG Source) { switch(Segment) { case SEGMENT_CS: /* Load CS Segment */ __asm__ volatile("mov %0, %%eax\n" "push %%eax\n" "lea label, %%eax\n" "push %%eax\n" "lret\n" "label:" : : "ri" (Source) : "eax"); break; case SEGMENT_DS: /* Load DS Segment */ __asm__ volatile("movl %0, %%ds" : : "r" (Source)); break; case SEGMENT_ES: /* Load ES Segment */ __asm__ volatile("movl %0, %%es" : : "r" (Source)); break; case SEGMENT_FS: /* Load FS Segment */ __asm__ volatile("movl %0, %%fs" : : "r" (Source)); break; case SEGMENT_GS: /* Load GS Segment */ __asm__ volatile("movl %0, %%gs" : : "r" (Source)); break; case SEGMENT_SS: /* Load SS Segment */ __asm__ volatile("movl %0, %%ss" : : "r" (Source)); break; } } /** * Loads Task Register (TR) with a segment selector that points to TSS. * * @param Source * Supplies the segment selector in the GDT describing the TSS. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::LoadTaskRegister(USHORT Source) { __asm__ volatile("ltr %0" : : "rm" (Source)); } /** * Orders memory accesses as seen by other processors. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::MemoryBarrier(VOID) { LONG Barrier; __asm__ volatile("xchg %%eax, %0" : : "m" (Barrier) : "%eax"); } /** * Reads the specified CPU control register and returns its value. * * @param ControlRegister * Supplies a number of a control register which controls the general behavior of a CPU. * * @return This routine returns the value stored in the control register. * * @since XT 1.0 */ XTCDECL ULONG_PTR AR::CpuFunctions::ReadControlRegister(IN USHORT ControlRegister) { ULONG_PTR Value; /* Read a value from specified CR register */ switch(ControlRegister) { case 0: /* Read value from CR0 */ __asm__ volatile("mov %%cr0, %0" : "=r" (Value) : : "memory"); break; case 2: /* Read value from CR2 */ __asm__ volatile("mov %%cr2, %0" : "=r" (Value) : : "memory"); break; case 3: /* Read value from CR3 */ __asm__ volatile("mov %%cr3, %0" : "=r" (Value) : : "memory"); break; case 4: /* Read value from CR4 */ __asm__ volatile("mov %%cr4, %0" : "=r" (Value) : : "memory"); break; default: /* Invalid control register set */ Value = 0; break; } /* Return value read from given CR register */ return Value; } /** * Reads the specified CPU debug register and returns its value. * * @param DebugRegister * Supplies a number of a debug register to read from. * * @return This routine returns the value stored in the specified debug register. * * @since XT 1.0 */ XTCDECL ULONG_PTR AR::CpuFunctions::ReadDebugRegister(IN USHORT DebugRegister) { ULONG_PTR Value; /* Read a value from specified DR register */ switch(DebugRegister) { case 0: /* Read value from DR0 */ __asm__ volatile("mov %%dr0, %0" : "=r" (Value)); break; case 1: /* Read value from DR1 */ __asm__ volatile("mov %%dr1, %0" : "=r" (Value)); break; case 2: /* Read value from DR2 */ __asm__ volatile("mov %%dr2, %0" : "=r" (Value)); break; case 3: /* Read value from DR3 */ __asm__ volatile("mov %%dr3, %0" : "=r" (Value)); break; case 4: /* Read value from DR4 */ __asm__ volatile("mov %%dr4, %0" : "=r" (Value)); break; case 5: /* Read value from DR5 */ __asm__ volatile("mov %%dr5, %0" : "=r" (Value)); break; case 6: /* Read value from DR6 */ __asm__ volatile("mov %%dr6, %0" : "=r" (Value)); break; case 7: /* Read value from DR7 */ __asm__ volatile("mov %%dr7, %0" : "=r" (Value)); break; default: /* Invalid debug register set */ Value = 0; break; } /* Return value read from given DR register */ return Value; } /** * Reads dualword from a memory location specified by an offset relative to the beginning of the FS segment. * * @param Offset * Specifies the offset from the beginning of FS segment. * * @return This routine returns the value read from the specified memory location relative to FS segment. * * @since XT 1.0 */ XTCDECL ULONG AR::CpuFunctions::ReadFSDualWord(ULONG Offset) { ULONG Value; __asm__ volatile("movl %%fs:%a[Offset], %k[Value]" : [Value] "=r" (Value) : [Offset] "ir" (Offset)); return Value; } /** * Reads a 64-bit value from the requested Model Specific Register (MSR). * * @param Register * Supplies the MSR to read. * * @return This routine returns the 64-bit MSR value. * * @since XT 1.0 */ XTCDECL ULONGLONG AR::CpuFunctions::ReadModelSpecificRegister(IN ULONG Register) { ULONGLONG Value; __asm__ volatile("rdmsr" : "=A" (Value) : "c" (Register)); return Value; } /** * Reads the contents of the MXCSR control/status register. * * @return This routine returns the contents of the MXCSR register as a 32-bit unsigned integer value. * * @since XT 1.0 */ XTCDECL UINT AR::CpuFunctions::ReadMxCsrRegister(VOID) { return __builtin_ia32_stmxcsr(); } /** * Reads the current value of the CPU's time-stamp counter. * * @return This routine returns the current instruction cycle count since the processor was started. * * @since XT 1.0 */ XTCDECL ULONGLONG AR::CpuFunctions::ReadTimeStampCounter(VOID) { ULONGLONG Value; __asm__ volatile("rdtsc" : "=A" (Value)); return Value; } /** * Reads the current value of the CPU's time-stamp counter and processor ID. * * @param TscAux * Supplies a pointer to a variable that receives the auxiliary TSC information (IA32_TSC_AUX). * * @return This routine returns the current instruction cycle count since the processor was last reset. * * @since XT 1.0 */ XTCDECL ULONGLONG AR::CpuFunctions::ReadTimeStampCounterProcessor(OUT PULONG TscAux) { ULONG Low, High; /* Execute the RDTSCP instruction */ __asm__ volatile("rdtscp" : "=a" (Low), "=d" (High), "=c" (*TscAux) ); /* Combine the two 32-bit registers into a single 64-bit unsigned integer and return the value */ return ((ULONGLONG)High << 32) | Low; } /** * Orders memory accesses as seen by other processors, without fence. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::ReadWriteBarrier(VOID) { __asm__ volatile("" : : : "memory"); } /** * Instructs the processor to set the interrupt flag. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::SetInterruptFlag(VOID) { __asm__ volatile("sti"); } /** * Stores GDT register into the given memory area. * * @param Destination * Supplies a pointer to the memory area where GDT will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::StoreGlobalDescriptorTable(OUT PVOID Destination) { __asm__ volatile("sgdt %0" : "=m" (*(PSHORT)Destination) : : "memory"); } /** * Stores IDT register into the given memory area. * * @param Destination * Supplies a pointer to the memory area where IDT will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::StoreInterruptDescriptorTable(OUT PVOID Destination) { __asm__ volatile("sidt %0" : "=m" (*(PSHORT)Destination) : : "memory"); } /** * Stores LDT register into the given memory area. * * @param Destination * Supplies a pointer to the memory area where LDT will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::StoreLocalDescriptorTable(OUT PVOID Destination) { __asm__ volatile("sldt %0" : "=m" (*(PSHORT)Destination) : : "memory"); } /** * Stores specified segment into the given memory area. * * @param Segment * Supplies a segment identification. * * @param Destination * Supplies a pointer to the memory area where segment data will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::StoreSegment(IN USHORT Segment, OUT PVOID Destination) { switch(Segment) { case SEGMENT_CS: __asm__ volatile("movl %%cs, %0" : "=r" (*(PUINT)Destination)); break; case SEGMENT_DS: __asm__ volatile("movl %%ds, %0" : "=r" (*(PUINT)Destination)); break; case SEGMENT_ES: __asm__ volatile("movl %%es, %0" : "=r" (*(PUINT)Destination)); break; case SEGMENT_FS: __asm__ volatile("movl %%fs, %0" : "=r" (*(PUINT)Destination)); break; case SEGMENT_GS: __asm__ volatile("movl %%gs, %0" : "=r" (*(PUINT)Destination)); break; case SEGMENT_SS: __asm__ volatile("movl %%ss, %0" : "=r" (*(PUINT)Destination)); break; default: Destination = NULLPTR; break; } } /** * Stores TR into the given memory area. * * @param Destination * Supplies a pointer to the memory area where TR will be stores. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::StoreTaskRegister(OUT PVOID Destination) { __asm__ volatile("str %0" : "=m" (*(PULONG)Destination) : : "memory"); } /** * Writes a value to the specified CPU control register. * * @param ControlRegister * Supplies a number of a control register which controls the general behavior of a CPU. * * @param Value * Suplies a value to write to the CR register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::WriteControlRegister(IN USHORT ControlRegister, IN UINT_PTR Value) { /* Write a value into specified control register */ switch(ControlRegister) { case 0: /* Write value to CR0 */ __asm__ volatile("mov %0, %%cr0" : : "r" (Value) : "memory"); break; case 2: /* Write value to CR2 */ __asm__ volatile("mov %0, %%cr2" : : "r" (Value) : "memory"); break; case 3: /* Write value to CR3 */ __asm__ volatile("mov %0, %%cr3" : : "r" (Value) : "memory"); break; case 4: /* Write value to CR4 */ __asm__ volatile("mov %0, %%cr4" : : "r" (Value) : "memory"); break; } } /** * Writes a value to the specified CPU debug register. * * @param DebugRegister * Supplies a number of a debug register for write operation. * * @param Value * Suplies a value to write to the specified DR register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::WriteDebugRegister(IN USHORT DebugRegister, IN UINT_PTR Value) { /* Write a value into specified debug register */ switch(DebugRegister) { case 0: /* Write value to DR0 */ __asm__ volatile("mov %0, %%dr0" : : "r" (Value) : "memory"); case 1: /* Write value to DR1 */ __asm__ volatile("mov %0, %%dr1" : : "r" (Value) : "memory"); case 2: /* Write value to DR2 */ __asm__ volatile("mov %0, %%dr2" : : "r" (Value) : "memory"); case 3: /* Write value to DR3 */ __asm__ volatile("mov %0, %%dr3" : : "r" (Value) : "memory"); case 4: /* Write value to DR4 */ __asm__ volatile("mov %0, %%dr4" : : "r" (Value) : "memory"); case 5: /* Write value to DR5 */ __asm__ volatile("mov %0, %%dr5" : : "r" (Value) : "memory"); case 6: /* Write value to DR6 */ __asm__ volatile("mov %0, %%dr6" : : "r" (Value) : "memory"); case 7: /* Write value to DR7 */ __asm__ volatile("mov %0, %%dr7" : : "r" (Value) : "memory"); } } /** * Writes the specified value to the program status and control (EFLAGS) register. * * @param Value * The value to write to the EFLAGS register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::WriteEflagsRegister(IN UINT_PTR Value) { __asm__ volatile("push %0\n" "popf" : : "rim" (Value)); } /** * Writes a 64-bit value to the requested Model Specific Register (MSR). * * @param Register * Supplies the MSR register to write. * * @param Value * Supplies the 64-bit value to write. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::WriteModelSpecificRegister(IN ULONG Register, IN ULONGLONG Value) { __asm__ volatile("wrmsr" : : "c" (Register), "A" (Value)); } /** * Yields a current thread running on the processor. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::CpuFunctions::YieldProcessor(VOID) { __asm__ volatile("pause" : : : "memory"); } ================================================ FILE: xtoskrnl/ar/i686/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ar/i686/data.cc * DESCRIPTION: I686 architecture-specific global and static data * DEVELOPERS: Rafal Kupiec */ #include /* Initial kernel boot stack */ UCHAR AR::ProcessorSupport::BootStack[KERNEL_STACK_SIZE] = {}; /* Double Fault gate */ UCHAR AR::ProcessorSupport::DoubleFaultTss[KTSS_IO_MAPS]; /* Initial kernel fault stack */ UCHAR AR::ProcessorSupport::FaultStack[KERNEL_STACK_SIZE] = {}; /* Initial GDT */ KGDTENTRY AR::ProcessorSupport::InitialGdt[GDT_ENTRIES] = {}; /* Initial IDT */ KIDTENTRY AR::ProcessorSupport::InitialIdt[IDT_ENTRIES] = {}; /* Initial Processor Block */ KPROCESSOR_BLOCK AR::ProcessorSupport::InitialProcessorBlock; /* Initial TSS */ KTSS AR::ProcessorSupport::InitialTss; /* Initial kernel NMI stack */ UCHAR AR::ProcessorSupport::NmiStack[KERNEL_STACK_SIZE] = {}; /* NMI task gate */ UCHAR AR::ProcessorSupport::NonMaskableInterruptTss[KTSS_IO_MAPS]; /* Unhandled interrupt routine */ PINTERRUPT_HANDLER AR::Traps::UnhandledInterruptRoutine = NULLPTR; ================================================ FILE: xtoskrnl/ar/i686/procsup.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ar/i686/procsup.cc * DESCRIPTION: I686 processor functionality support * DEVELOPERS: Rafal Kupiec */ #include /** * Gets the base address of the kernel boot stack. * * @return This routine returns a pointer to the kernel boot stack. * * @since XT 1.0 */ XTAPI PVOID AR::ProcessorSupport::GetBootStack(VOID) { /* Return base address of kernel boot stack */ return (PVOID)((ULONG_PTR)BootStack + KERNEL_STACK_SIZE); } XTAPI VOID AR::ProcessorSupport::GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType, OUT PVOID *TrampolineCode, OUT PULONG_PTR TrampolineSize) { /* Get trampoline information */ switch(TrampolineType) { case TrampolineApStartup: /* Get AP startup trampoline information */ *TrampolineCode = (PVOID)ArStartApplicationProcessor; *TrampolineSize = (ULONG_PTR)ArStartApplicationProcessorEnd - (ULONG_PTR)ArStartApplicationProcessor; break; default: /* Unknown trampoline type */ *TrampolineCode = NULLPTR; *TrampolineSize = 0; break; } } /** * Identifies processor type (vendor, model, stepping) and stores them in Processor Control Block (PRCB). * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::IdentifyProcessor(VOID) { PKPROCESSOR_CONTROL_BLOCK Prcb; CPUID_REGISTERS CpuRegisters; CPUID_SIGNATURE CpuSignature; /* Get current processor control block */ Prcb = KE::Processor::GetCurrentProcessorControlBlock(); /* Get CPU vendor by issueing CPUID instruction */ RtlZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_VENDOR_STRING; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU vendor in processor control block */ Prcb->CpuId.Vendor = (CPU_VENDOR)CpuRegisters.Ebx; *(PULONG)&Prcb->CpuId.VendorName[0] = CpuRegisters.Ebx; *(PULONG)&Prcb->CpuId.VendorName[4] = CpuRegisters.Edx; *(PULONG)&Prcb->CpuId.VendorName[8] = CpuRegisters.Ecx; Prcb->CpuId.VendorName[12] = '\0'; /* Get CPU standard features */ RtlZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU signature in processor control block */ CpuSignature = *(PCPUID_SIGNATURE)&CpuRegisters.Eax; Prcb->CpuId.Family = CpuSignature.Family; Prcb->CpuId.Model = CpuSignature.Model; Prcb->CpuId.Stepping = CpuSignature.Stepping; /* CPU vendor specific quirks */ if(Prcb->CpuId.Vendor == CPU_VENDOR_AMD) { /* AMD CPU */ if(CpuSignature.Family == 0xF) { Prcb->CpuId.Family += CpuSignature.ExtendedFamily; Prcb->CpuId.Model += (CpuSignature.ExtendedModel << 4); } } else if(Prcb->CpuId.Vendor == CPU_VENDOR_INTEL) { /* Intel CPU */ if(CpuSignature.Family == 0xF) { Prcb->CpuId.Family += CpuSignature.ExtendedFamily; } if((CpuSignature.Family == 0x6) || (CpuSignature.Family == 0xF)) { Prcb->CpuId.Model += (CpuSignature.ExtendedModel << 4); } } else { /* Unknown CPU vendor */ Prcb->CpuId.Vendor = CPU_VENDOR_UNKNOWN; } /* Identify processor features */ IdentifyProcessorFeatures(); } /** * Identifies processor features and stores them in Processor Control Block (PRCB). * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::IdentifyProcessorFeatures(VOID) { ULONG MaxExtendedLeaf, MaxStandardLeaf; PKPROCESSOR_CONTROL_BLOCK Prcb; CPUID_REGISTERS CpuRegisters; /* Get current processor control block */ Prcb = KE::Processor::GetCurrentProcessorControlBlock(); /* Get maximum CPUID standard leaf */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_VENDOR_STRING; AR::CpuFunctions::CpuId(&CpuRegisters); MaxStandardLeaf = CpuRegisters.Eax; /* Get maximum CPUID extended leaf */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_EXTENDED_MAX; AR::CpuFunctions::CpuId(&CpuRegisters); MaxExtendedLeaf = CpuRegisters.Eax; /* Check if CPU supports standard features leaf */ if(MaxStandardLeaf >= CPUID_GET_STANDARD1_FEATURES) { /* Get CPU standard features */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU standard features in processor control block */ if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_SSE3) Prcb->CpuId.FeatureBits |= KCF_SSE3; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_VMX) Prcb->CpuId.FeatureBits |= KCF_VMX; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_SSSE3) Prcb->CpuId.FeatureBits |= KCF_SSSE3; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_SSE4_1) Prcb->CpuId.FeatureBits |= KCF_SSE41; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_SSE4_2) Prcb->CpuId.FeatureBits |= KCF_SSE42; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_X2APIC) Prcb->CpuId.FeatureBits |= KCF_X2APIC; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_POPCNT) Prcb->CpuId.FeatureBits |= KCF_POPCNT; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_TSC_DEADLINE) Prcb->CpuId.FeatureBits |= KCF_TSC_DEADLINE; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_AES) Prcb->CpuId.FeatureBits |= KCF_AES; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_XSAVE) Prcb->CpuId.FeatureBits |= KCF_XSAVE; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_AVX) Prcb->CpuId.FeatureBits |= KCF_AVX; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_RDRAND) Prcb->CpuId.FeatureBits |= KCF_RDRAND; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_VME) Prcb->CpuId.FeatureBits |= KCF_VME; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PSE) Prcb->CpuId.FeatureBits |= KCF_LARGE_PAGE; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_TSC) Prcb->CpuId.FeatureBits |= KCF_RDTSC; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PAE) Prcb->CpuId.FeatureBits |= KCF_PAE; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_MCE) Prcb->CpuId.FeatureBits |= KCF_MCE; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_CX8) Prcb->CpuId.FeatureBits |= KCF_CMPXCHG8B; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_APIC) Prcb->CpuId.FeatureBits |= KCF_APIC; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_SEP) Prcb->CpuId.FeatureBits |= KCF_FAST_SYSCALL; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_MTRR) Prcb->CpuId.FeatureBits |= KCF_MTRR; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PGE) Prcb->CpuId.FeatureBits |= KCF_GLOBAL_PAGE; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_MCA) Prcb->CpuId.FeatureBits |= KCF_MCA; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_CMOV) Prcb->CpuId.FeatureBits |= KCF_CMOV; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PAT) Prcb->CpuId.FeatureBits |= KCF_PAT; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PSE36) Prcb->CpuId.FeatureBits |= KCF_PSE36; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_CLFLUSH) Prcb->CpuId.FeatureBits |= KCF_CLFLUSH; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_FXSR) Prcb->CpuId.FeatureBits |= KCF_FXSR; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_ACPI) Prcb->CpuId.FeatureBits |= KCF_ACPI; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_MMX) Prcb->CpuId.FeatureBits |= KCF_MMX; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_SSE) Prcb->CpuId.FeatureBits |= KCF_SSE; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_SSE2) Prcb->CpuId.FeatureBits |= KCF_SSE2; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_HTT) Prcb->CpuId.FeatureBits |= KCF_SMT; } /* Check if CPU supports standard7 features leaf */ if(MaxStandardLeaf >= CPUID_GET_STANDARD7_FEATURES) { /* Get CPU standard features */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_STANDARD7_FEATURES; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU standard7 features in processor control block */ if(CpuRegisters.Ebx & CPUID_FEATURES_EBX_FSGSBASE) Prcb->CpuId.FeatureBits |= KCF_FSGSBASE; if(CpuRegisters.Ebx & CPUID_FEATURES_EBX_AVX2) Prcb->CpuId.FeatureBits |= KCF_AVX2; if(CpuRegisters.Ebx & CPUID_FEATURES_EBX_SMEP) Prcb->CpuId.FeatureBits |= KCF_SMEP; if(CpuRegisters.Ebx & CPUID_FEATURES_EBX_RDSEED) Prcb->CpuId.FeatureBits |= KCF_RDSEED; if(CpuRegisters.Ebx & CPUID_FEATURES_EBX_SMAP) Prcb->CpuId.FeatureBits |= KCF_SMAP; if(CpuRegisters.Ebx & CPUID_FEATURES_EBX_SHA) Prcb->CpuId.FeatureBits |= KCF_SHA; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_LA57) Prcb->CpuId.FeatureBits |= KCF_LA57; } /* Check if CPU supports power management leaf */ if(MaxStandardLeaf >= CPUID_GET_POWER_MANAGEMENT) { /* Get CPU power management features */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_POWER_MANAGEMENT; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU power management features in processor control block */ if(CpuRegisters.Eax & CPUID_FEATURES_EAX_ARAT) Prcb->CpuId.FeatureBits |= KCF_ARAT; } /* Check if CPU supports extended features leaf */ if(MaxExtendedLeaf >= CPUID_GET_EXTENDED_FEATURES) { /* Get CPU extended features */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_EXTENDED_FEATURES; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU extended features in processor control block */ if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_SVM) Prcb->CpuId.ExtendedFeatureBits |= KCF_SVM; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_SSE4A) Prcb->CpuId.ExtendedFeatureBits |= KCF_SSE4A; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_FMA4) Prcb->CpuId.ExtendedFeatureBits |= KCF_FMA4; if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_TOPOLOGY_EXTENSIONS) Prcb->CpuId.ExtendedFeatureBits |= KCF_TOPOEXT; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_SYSCALL_SYSRET) Prcb->CpuId.ExtendedFeatureBits |= KCF_SYSCALL; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_NX) Prcb->CpuId.ExtendedFeatureBits |= KCF_NX_BIT; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_RDTSCP) Prcb->CpuId.ExtendedFeatureBits |= KCF_RDTSCP; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_LONG_MODE) Prcb->CpuId.ExtendedFeatureBits |= KCF_64BIT; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_3DNOW_EXT) Prcb->CpuId.ExtendedFeatureBits |= KCF_3DNOW_EXT; if(CpuRegisters.Edx & CPUID_FEATURES_EDX_3DNOW) Prcb->CpuId.ExtendedFeatureBits |= KCF_3DNOW; } /* Check if CPU supports advanced power management leaf */ if(MaxExtendedLeaf >= CPUID_GET_ADVANCED_POWER_MANAGEMENT) { /* Get CPU advanced power management features */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_ADVANCED_POWER_MANAGEMENT; AR::CpuFunctions::CpuId(&CpuRegisters); /* Store CPU advanced power management features in processor control block */ if(CpuRegisters.Edx & CPUID_FEATURES_EDX_TSCI) Prcb->CpuId.ExtendedFeatureBits |= KCF_INVARIANT_TSC; } } /** * Initializes the kernel's Global Descriptor Table (GDT). * * @param ProcessorBlock * Supplies a pointer to the processor block to use. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeGdt(IN PKPROCESSOR_BLOCK ProcessorBlock) { /* Initialize GDT entries */ SetGdtEntry(ProcessorBlock->GdtBase, KGDT_NULL, 0x0, 0x0, KGDT_TYPE_NONE, KGDT_DPL_SYSTEM, 0); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R0_CODE, 0x0, 0xFFFFFFFF, KGDT_TYPE_CODE, KGDT_DPL_SYSTEM, 2); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R0_DATA, 0x0, 0xFFFFFFFF, KGDT_TYPE_DATA, KGDT_DPL_SYSTEM, 2); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R3_CODE, 0x0, 0xFFFFFFFF, KGDT_TYPE_CODE, KGDT_DPL_USER, 2); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R3_DATA, 0x0, 0xFFFFFFFF, KGDT_TYPE_DATA, KGDT_DPL_USER, 2); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_SYS_TSS, (ULONG_PTR)ProcessorBlock->TssBase, sizeof(KTSS) - 1, I686_TSS, KGDT_DPL_SYSTEM, 0); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R0_PB, (ULONG_PTR)ProcessorBlock, sizeof(KPROCESSOR_BLOCK), KGDT_TYPE_DATA, KGDT_DPL_SYSTEM, 2); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R3_TEB, 0x0, 0xFFF, KGDT_TYPE_DATA | KGDT_DESCRIPTOR_ACCESSED, KGDT_DPL_USER, 2); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_VDM_TILE, 0x0400, 0xFFFF, KGDT_TYPE_DATA, KGDT_DPL_USER, 0); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_R0_LDT, 0x0, 0x0, I686_LDT, KGDT_DPL_SYSTEM, 0); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_DF_TSS, 0x20000, 0xFFFF, I686_TSS, KGDT_DPL_SYSTEM, 0); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_NMI_TSS, 0x20000, 0xFFFF, I686_TSS, KGDT_DPL_SYSTEM, 0); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_VDBS, 0xB8000, 0x3FFF, KGDT_TYPE_DATA, KGDT_DPL_SYSTEM, 0); SetGdtEntry(ProcessorBlock->GdtBase, KGDT_ALIAS, (ULONG_PTR)ProcessorBlock->GdtBase, (GDT_ENTRIES * sizeof(KGDTENTRY)) - 1, KGDT_TYPE_DATA, KGDT_DPL_SYSTEM, 0); } /** * Initializes the kernel's Interrupt Descriptor Table (IDT). * * @param ProcessorBlock * Supplies a pointer to the processor block to use. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeIdt(IN PKPROCESSOR_BLOCK ProcessorBlock) { UINT Vector; /* Fill in all vectors */ for(Vector = 0; Vector < IDT_ENTRIES; Vector++) { /* Set the IDT to handle unexpected interrupts */ SetIdtGate(ProcessorBlock->IdtBase, Vector, (PVOID)ArInterruptEntry[Vector], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); } /* Setup IDT handlers for known interrupts and traps */ SetIdtGate(ProcessorBlock->IdtBase, 0x00, (PVOID)ArTrapEntry[0x00], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x01, (PVOID)ArTrapEntry[0x01], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x02, (PVOID)ArTrapEntry[0x02], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TASK_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x03, (PVOID)ArTrapEntry[0x03], KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x04, (PVOID)ArTrapEntry[0x04], KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x05, (PVOID)ArTrapEntry[0x05], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x06, (PVOID)ArTrapEntry[0x06], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x07, (PVOID)ArTrapEntry[0x07], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x08, (PVOID)ArTrapEntry[0x08], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TASK_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x09, (PVOID)ArTrapEntry[0x09], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x0A, (PVOID)ArTrapEntry[0x0A], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x0B, (PVOID)ArTrapEntry[0x0B], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x0C, (PVOID)ArTrapEntry[0x0C], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x0D, (PVOID)ArTrapEntry[0x0D], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x0E, (PVOID)ArTrapEntry[0x0E], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x10, (PVOID)ArTrapEntry[0x10], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x11, (PVOID)ArTrapEntry[0x11], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x12, (PVOID)ArTrapEntry[0x12], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x13, (PVOID)ArTrapEntry[0x13], KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x2A, (PVOID)ArTrapEntry[0x2A], KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x2B, (PVOID)ArTrapEntry[0x2B], KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x2C, (PVOID)ArTrapEntry[0x2C], KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x2D, (PVOID)ArTrapEntry[0x2D], KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_INTERRUPT_GATE); SetIdtGate(ProcessorBlock->IdtBase, 0x2E, (PVOID)ArTrapEntry[0x2E], KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_INTERRUPT_GATE); } /** * Initializes i686 processor specific structures. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeProcessor(IN PVOID ProcessorStructures) { KDESCRIPTOR GdtDescriptor, IdtDescriptor; PVOID KernelBootStack, KernelFaultStack, KernelNmiStack; PKPROCESSOR_BLOCK ProcessorBlock; PKGDTENTRY Gdt; PKIDTENTRY Idt; PKTSS Tss; /* Check if processor structures buffer provided */ if(ProcessorStructures) { /* Assign CPU structures from provided buffer */ InitializeProcessorStructures(ProcessorStructures, &Gdt, &Tss, &ProcessorBlock, &KernelBootStack, &KernelFaultStack, &KernelNmiStack); /* Use global IDT */ Idt = InitialIdt; } else { /* Use initial structures */ Gdt = InitialGdt; Idt = InitialIdt; Tss = &InitialTss; KernelBootStack = (PVOID)((ULONG_PTR)&BootStack + KERNEL_STACK_SIZE); KernelFaultStack = (PVOID)((ULONG_PTR)&FaultStack + KERNEL_STACK_SIZE); KernelNmiStack = (PVOID)((ULONG_PTR)&NmiStack + KERNEL_STACK_SIZE); ProcessorBlock = &InitialProcessorBlock; } /* Initialize processor block */ InitializeProcessorBlock(ProcessorBlock, Gdt, Idt, Tss, KernelFaultStack); /* Initialize GDT, IDT and TSS */ InitializeGdt(ProcessorBlock); InitializeIdt(ProcessorBlock); InitializeTss(ProcessorBlock, KernelBootStack, KernelFaultStack, KernelNmiStack); /* Set GDT and IDT descriptors */ GdtDescriptor.Base = Gdt; GdtDescriptor.Limit = (GDT_ENTRIES * sizeof(KGDTENTRY)) - 1; IdtDescriptor.Base = Idt; IdtDescriptor.Limit = (IDT_ENTRIES * sizeof(KIDTENTRY)) - 1; /* Load GDT, IDT and TSS */ AR::CpuFunctions::LoadGlobalDescriptorTable(&GdtDescriptor.Limit); AR::CpuFunctions::LoadInterruptDescriptorTable(&IdtDescriptor.Limit); AR::CpuFunctions::LoadTaskRegister((UINT)KGDT_SYS_TSS); /* Initialize segment registers */ InitializeSegments(); /* Initialize processor registers */ InitializeProcessorRegisters(); /* Identify processor */ IdentifyProcessor(); } /** * Initializes processor block. * * @param ProcessorBlock * Supplies a pointer to the processor block to initialize. * * @param Gdt * Supplies a pointer to the GDT for this processor block. * * @param Idt * Supplies a pointer to the IDT for this processor block. * * @param Tss * Supplies a pointer to the TSS for this processor block. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeProcessorBlock(OUT PKPROCESSOR_BLOCK ProcessorBlock, IN PKGDTENTRY Gdt, IN PKIDTENTRY Idt, IN PKTSS Tss, IN PVOID DpcStack) { /* Set processor block and processor control block */ ProcessorBlock->Self = ProcessorBlock; ProcessorBlock->CurrentPrcb = &ProcessorBlock->Prcb; /* Set GDT, IDT and TSS descriptors */ ProcessorBlock->GdtBase = (PKGDTENTRY)(PVOID)Gdt; ProcessorBlock->IdtBase = Idt; ProcessorBlock->TssBase = Tss; /* Setup DPC stack */ ProcessorBlock->Prcb.DpcStack = DpcStack; /* Setup processor control block */ ProcessorBlock->Prcb.CpuNumber = ProcessorBlock->CpuNumber; ProcessorBlock->Prcb.SetMember = 1 << ProcessorBlock->CpuNumber; ProcessorBlock->Prcb.MultiThreadProcessorSet = 1 << ProcessorBlock->CpuNumber; /* Clear DR6 and DR7 registers */ ProcessorBlock->Prcb.ProcessorState.SpecialRegisters.KernelDr6 = 0; ProcessorBlock->Prcb.ProcessorState.SpecialRegisters.KernelDr7 = 0; /* Set process and thread information */ ProcessorBlock->Prcb.CurrentThread = &(KE::KThread::GetInitialThread())->ThreadControlBlock; ProcessorBlock->Prcb.CurrentThread->ApcState.Process = &(KE::KProcess::GetInitialProcess())->ProcessControlBlock; ProcessorBlock->Prcb.IdleThread = &(KE::KThread::GetInitialThread())->ThreadControlBlock; ProcessorBlock->Prcb.NextThread = NULLPTR; /* Set initial runlevel */ ProcessorBlock->RunLevel = PASSIVE_LEVEL; } /** * Initializes processor registers and other boot structures. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeProcessorRegisters(VOID) { /* Clear EFLAGS register */ AR::CpuFunctions::WriteEflagsRegister(0); /* Enable write-protection */ AR::CpuFunctions::WriteControlRegister(0, AR::CpuFunctions::ReadControlRegister(0) | CR0_WP); } /** * Initializes i686 processor specific structures with provided memory buffer. * * @param ProcessorStructures * Supplies a pointer to the allocated buffer with processor structures. * * @param Gdt * Supplies a pointer to the GDT. * * @param Tss * Supplies a pointer to the TSS. * * @param ProcessorBlock * Supplies a pointer to the processor block. * * @param KernelBootStack * Supplies a pointer to the kernel boot stack. * * @param KernelFaultStack * Supplies a pointer to the kernel fault stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeProcessorStructures(IN PVOID ProcessorStructures, OUT PKGDTENTRY *Gdt, OUT PKTSS *Tss, OUT PKPROCESSOR_BLOCK *ProcessorBlock, OUT PVOID *KernelBootStack, OUT PVOID *KernelFaultStack, OUT PVOID *KernelNmiStack) { UINT_PTR Address; /* Align address to page size boundary and move to kernel boot stack */ Address = ROUND_UP((UINT_PTR)ProcessorStructures, MM_PAGE_SIZE) + KERNEL_STACK_SIZE; /* Assign a space for kernel boot stack and advance */ if(KernelBootStack != NULLPTR) { /* Return kernel boot stack address */ *KernelBootStack = (PVOID)Address; } Address += KERNEL_STACK_SIZE; /* Assign a space for kernel fault stack and advance */ if(KernelFaultStack != NULLPTR) { /* Return kernel fault stack address */ *KernelFaultStack = (PVOID)Address; } Address += KERNEL_STACK_SIZE; /* Assign a space for kernel NMI stack, no advance needed as stack grows down */ if(KernelNmiStack != NULLPTR) { /* Return kernel NMI stack address */ *KernelNmiStack = (PVOID)Address; } /* Assign a space for GDT and advance */ if(Gdt != NULLPTR) { /* Return GDT base address */ *Gdt = (PKGDTENTRY)(PVOID)Address; } Address += (GDT_ENTRIES * sizeof(KGDTENTRY)); /* Assign a space for TSS and advance */ if(Tss != NULLPTR) { *Tss = (PKTSS)(PVOID)Address; } Address += sizeof(KTSS); /* Assign a space for Processor Block and advance */ if(ProcessorBlock != NULLPTR) { /* Return processor block address */ *ProcessorBlock = (PKPROCESSOR_BLOCK)(PVOID)Address; } } /** * Initializes segment registers. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeSegments(VOID) { /* Initialize segments */ AR::CpuFunctions::LoadSegment(SEGMENT_CS, KGDT_R0_CODE); AR::CpuFunctions::LoadSegment(SEGMENT_DS, KGDT_R3_DATA | RPL_MASK); AR::CpuFunctions::LoadSegment(SEGMENT_ES, KGDT_R3_DATA | RPL_MASK); AR::CpuFunctions::LoadSegment(SEGMENT_FS, KGDT_R0_PB); AR::CpuFunctions::LoadSegment(SEGMENT_GS, 0); AR::CpuFunctions::LoadSegment(SEGMENT_SS, KGDT_R0_DATA); } /** * Initializes the kernel's Task State Segment (TSS). * * @param ProcessorBlock * Supplies a pointer to the processor block to use. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::InitializeTss(IN PKPROCESSOR_BLOCK ProcessorBlock, IN PVOID KernelBootStack, IN PVOID KernelFaultStack, IN PVOID KernelNmiStack) { PKGDTENTRY TssEntry; /* Setup System TSS entry in Global Descriptor Table */ TssEntry = (PKGDTENTRY)(&(ProcessorBlock->GdtBase[KGDT_SYS_TSS / sizeof(KGDTENTRY)])); TssEntry->LimitLow = sizeof(KTSS) - 1; TssEntry->Bits.LimitHigh = 0; TssEntry->Bits.Dpl = 0; TssEntry->Bits.Present = 1; TssEntry->Bits.Type = I686_TSS; /* Clear I/O map */ RtlSetMemory(ProcessorBlock->TssBase->IoMaps[0].IoMap, 0xFF, IOPM_FULL_SIZE); /* Fill Interrupt Direction Maps with zeroes */ RtlZeroMemory(ProcessorBlock->TssBase->IoMaps[0].DirectionMap, IOPM_DIRECTION_MAP_SIZE); /* Enable DPMI support */ ProcessorBlock->TssBase->IoMaps[0].DirectionMap[0] = 4; ProcessorBlock->TssBase->IoMaps[0].DirectionMap[3] = 0x18; ProcessorBlock->TssBase->IoMaps[0].DirectionMap[4] = 0x18; /* Fill default Interrupt Direction Map with zeroes */ RtlZeroMemory(ProcessorBlock->TssBase->IntDirectionMap, IOPM_DIRECTION_MAP_SIZE); /* Enable DPMI support */ ProcessorBlock->TssBase->IntDirectionMap[0] = 4; ProcessorBlock->TssBase->IntDirectionMap[3] = 0x18; ProcessorBlock->TssBase->IntDirectionMap[4] = 0x18; /* Set I/O map base and disable traps */ ProcessorBlock->TssBase->IoMapBase = sizeof(KTSS); ProcessorBlock->TssBase->Flags = 0; /* Set CR3, LDT and SS */ ProcessorBlock->TssBase->CR3 = AR::CpuFunctions::ReadControlRegister(3); ProcessorBlock->TssBase->LDT = 0; ProcessorBlock->TssBase->Ss0 = KGDT_R0_DATA; /* Initialize task gates for DoubleFault and NMI traps */ SetDoubleFaultTssEntry(ProcessorBlock, KernelFaultStack); SetNonMaskableInterruptTssEntry(ProcessorBlock, KernelNmiStack); } /** * Initializes the DoubleFault TSS entry in the Global Descriptor Table. * * @param ProcessorBlock * Supplies a pointer to the processor block to use. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::SetDoubleFaultTssEntry(IN PKPROCESSOR_BLOCK ProcessorBlock, IN PVOID KernelFaultStack) { PKGDTENTRY TaskGateEntry, TssEntry; PKTSS Tss; /* Setup task gate for DoubleFault trap */ TaskGateEntry = (PKGDTENTRY)&ProcessorBlock->IdtBase[8]; TaskGateEntry->Bits.Dpl = 0; TaskGateEntry->Bits.Present = 1; TaskGateEntry->Bits.Type = I686_TASK_GATE; ((PKIDTENTRY)TaskGateEntry)->Selector = KGDT_DF_TSS; /* Initialize DoubleFault TSS and set initial state */ Tss = (PKTSS)DoubleFaultTss; Tss->IoMapBase = sizeof(KTSS); Tss->Flags = 0; Tss->LDT = 0; Tss->CR3 = AR::CpuFunctions::ReadControlRegister(3); Tss->Esp = (ULONG_PTR)KernelFaultStack; Tss->Esp0 = (ULONG_PTR)KernelFaultStack; Tss->Eip = (ULONG)(ULONG_PTR)ArTrapEntry[0x08]; Tss->Cs = KGDT_R0_CODE; Tss->Ds = KGDT_R3_DATA | RPL_MASK; Tss->Es = KGDT_R3_DATA | RPL_MASK; Tss->Fs = KGDT_R0_PB; Tss->Ss = KGDT_R0_DATA; Tss->Ss0 = KGDT_R0_DATA; /* Setup DoubleFault TSS entry in Global Descriptor Table */ TssEntry = (PKGDTENTRY)(&(ProcessorBlock->GdtBase[KGDT_DF_TSS / sizeof(KGDTENTRY)])); TssEntry->BaseLow = ((ULONG_PTR)Tss & 0xFFFF); TssEntry->Bytes.BaseMiddle = ((ULONG_PTR)Tss >> 16); TssEntry->Bytes.BaseHigh = ((ULONG_PTR)Tss >> 24); TssEntry->LimitLow = 0x68; TssEntry->Bits.LimitHigh = 0; TssEntry->Bits.Dpl = 0; TssEntry->Bits.Present = 1; TssEntry->Bits.Type = I686_TSS; } /** * Fills in an i686 GDT entry. * * @param Gdt * Supplies a pointer to the GDT. * * @param Selector * Specifies a segment selector of the GDT entry. * * @param Base * Specifies a base address value of the descriptor. * * @param Limit * Specifies a descriptor limit. * * @param Type * Specifies a type of the descriptor. * * @param Dpl * Specifies the descriptor privilege level. * * @param SegmentMode * Specifies a segment mode of the descriptor. * * @return This routine does not return any value * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::SetGdtEntry(IN PKGDTENTRY Gdt, IN USHORT Selector, IN ULONG_PTR Base, IN ULONG Limit, IN UCHAR Type, IN UCHAR Dpl, IN UCHAR SegmentMode) { PKGDTENTRY GdtEntry; UCHAR Granularity; /* Set the granularity flag depending on descriptor limit */ if(Limit < 0x100000) { /* Limit is in 1B blocks */ Granularity = 0; } else { /* Limit is in 4KB blocks */ Granularity = 1; Limit >>= 12; } /* Get GDT entry */ GdtEntry = (PKGDTENTRY)((ULONG_PTR)Gdt + (Selector & ~RPL_MASK)); /* Set GDT descriptor base */ GdtEntry->BaseLow = (Base & 0xFFFF); GdtEntry->Bytes.BaseMiddle = ((Base >> 16) & 0xFF); GdtEntry->Bytes.BaseHigh = ((Base >> 24) & 0xFF); /* Set descriptor limit */ GdtEntry->LimitLow = (Limit & 0xFFFF); GdtEntry->Bits.LimitHigh = ((Limit >> 16) & 0xF); /* Initialize GDT entry */ GdtEntry->Bits.DefaultBig = !!(SegmentMode & 2); GdtEntry->Bits.Dpl = (Dpl & 0x3); GdtEntry->Bits.Granularity = Granularity; GdtEntry->Bits.Reserved0 = 0; GdtEntry->Bits.Present = (Type != 0); GdtEntry->Bits.System = 0; GdtEntry->Bits.Type = (Type & 0x1F); } /** * Updates an existing i686 GDT entry with new base address. * * @param Gdt * Supplies a pointer to the GDT. * * @param Selector * Specifies a segment selector of the GDT entry. * * @param Base * Specifies a base address value of the descriptor. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::SetGdtEntryBase(IN PKGDTENTRY Gdt, IN USHORT Selector, IN ULONG_PTR Base) { PKGDTENTRY GdtEntry; /* Get GDT entry */ GdtEntry = (PKGDTENTRY)((ULONG_PTR)Gdt + (Selector & ~RPL_MASK)); /* Set new GDT descriptor base */ GdtEntry->BaseLow = (Base & 0xFFFF); GdtEntry->Bytes.BaseMiddle = ((Base >> 16) & 0xFF); GdtEntry->Bytes.BaseHigh = ((Base >> 24) & 0xFF); } /** * Fills in a call, interrupt, task or trap gate entry. * * @param Idt * Supplies a pointer to IDT structure, where gate is located. * * @param Vector * Supplies a gate vector pointing to the interrupt gate in the IDT * * @param Handler * Supplies a pointer to the interrupt handler of the specified gate. * * @param Selector * Supplies the code selector the gate should run in. * * @param Ist * Supplies the interrupt stack table entry the gate should run in. * * @param Access * Supplies the gate access rights. * * @param Type * Supplies the gate type. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::SetIdtGate(IN PKIDTENTRY Idt, IN USHORT Vector, IN PVOID Handler, IN USHORT Selector, IN USHORT Ist, IN USHORT Dpl, IN USHORT Type) { /* Set the handler's address */ Idt[Vector].Offset = (USHORT)((ULONG)Handler & 0xFFFF); Idt[Vector].ExtendedOffset = (USHORT)((ULONG)Handler >> 16); /* Set the code segment selector */ Idt[Vector].Selector = Selector; /* Initialize the gate's attributes and flags */ Idt[Vector].Access = 0; Idt[Vector].Dpl = Dpl; Idt[Vector].Present = 1; Idt[Vector].Type = Type; } /** * Initializes the Non-Maskable Interrupt TSS entry in the Global Descriptor Table. * * @param ProcessorBlock * Supplies a pointer to the processor block to use. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID AR::ProcessorSupport::SetNonMaskableInterruptTssEntry(IN PKPROCESSOR_BLOCK ProcessorBlock, IN PVOID KernelNmiStack) { PKGDTENTRY TaskGateEntry, TssEntry; PKTSS Tss; /* Setup task gate for NMI */ TaskGateEntry = (PKGDTENTRY)&ProcessorBlock->IdtBase[2]; TaskGateEntry->Bits.Dpl = 0; TaskGateEntry->Bits.Present = 1; TaskGateEntry->Bits.Type = I686_TASK_GATE; ((PKIDTENTRY)TaskGateEntry)->Selector = KGDT_NMI_TSS; /* Initialize NMI TSS and set initial state */ Tss = (PKTSS)NonMaskableInterruptTss; Tss->IoMapBase = sizeof(KTSS); Tss->Flags = 0; Tss->LDT = 0; Tss->CR3 = AR::CpuFunctions::ReadControlRegister(3); Tss->Esp = (ULONG_PTR)KernelNmiStack; Tss->Esp0 = (ULONG_PTR)KernelNmiStack; Tss->Eip = (ULONG)(ULONG_PTR)ArTrapEntry[0x02]; Tss->Cs = KGDT_R0_CODE; Tss->Ds = KGDT_R3_DATA | RPL_MASK; Tss->Es = KGDT_R3_DATA | RPL_MASK; Tss->Fs = KGDT_R0_PB; Tss->Ss = KGDT_R0_DATA; Tss->Ss0 = KGDT_R0_DATA; /* Setup NMI TSS entry in Global Descriptor Table */ TssEntry = (PKGDTENTRY)(&(ProcessorBlock->GdtBase[KGDT_NMI_TSS / sizeof(KGDTENTRY)])); TssEntry->BaseLow = ((ULONG_PTR)Tss & 0xFFFF); TssEntry->Bytes.BaseMiddle = ((ULONG_PTR)Tss >> 16); TssEntry->Bytes.BaseHigh = ((ULONG_PTR)Tss >> 24); TssEntry->LimitLow = 0x68; TssEntry->Bits.LimitHigh = 0; TssEntry->Bits.Dpl = 0; TssEntry->Bits.Present = 1; TssEntry->Bits.Type = I686_TSS; } ================================================ FILE: xtoskrnl/ar/i686/traps.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ar/i686/traps.cc * DESCRIPTION: I686 system traps * DEVELOPERS: Rafal Kupiec */ #include /** * Dispatches the interrupt provided by common interrupt handler. * * @param TrapFrame * Supplies a kernel trap frame pushed by common interrupt handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::DispatchInterrupt(IN PKTRAP_FRAME TrapFrame) { PINTERRUPT_HANDLER Handler; /* Read the handler pointer from the CPU's interrupt dispatch table */ Handler = (PINTERRUPT_HANDLER)AR::CpuFunctions::ReadFSDualWord(FIELD_OFFSET(KPROCESSOR_BLOCK, InterruptDispatchTable) + (TrapFrame->Vector * sizeof(PINTERRUPT_HANDLER))); /* Check if the interrupt has a handler registered */ if(Handler != NULLPTR) { /* Call the handler */ Handler(TrapFrame); } else if(UnhandledInterruptRoutine != NULLPTR) { /* Call the unhandled interrupt routine */ UnhandledInterruptRoutine(TrapFrame); } else { /* Dispatcher not initialized, print a debug message */ DebugPrint(L"ERROR: Caught unhandled interrupt: 0x%.2lX\n", TrapFrame->Vector); } } /** * Dispatches the trap provided by common trap handler. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::DispatchTrap(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Caught trap: 0x%.2lX with error code: %.4lX at EIP: 0x%.8lX\n" L"EAX: 0x%.8lX, EBX: 0x%.8lX, ECX: 0x%.8lX, EDX: 0x%.8lX\n" L"EBP: 0x%.8lX, ESP: 0x%.8lX, EDI: 0x%.8lX, ESI: 0x%.8lX\n" L"DR0: 0x%.8lX, DR1: 0x%.8lX, DR2: 0x%.8lX, DR3: 0x%.8lX\n" L"DR6: 0x%.8lX, DR7: 0x%.8lX\n" L"CR2: 0x%.8lX, CR3: 0x%.8lX, CS: 0x%.8lX, DS: 0x%.8hX\n" L"ES: 0x%.8hX, FS: 0x%.8hX, GS: 0x%.8hX, SS: 0x%.8lX\n", TrapFrame->Vector, TrapFrame->ErrorCode, TrapFrame->Eip, TrapFrame->Eax, TrapFrame->Ebx, TrapFrame->Ecx, TrapFrame->Edx, TrapFrame->Ebp, TrapFrame->Esp, TrapFrame->Edi, TrapFrame->Esi, TrapFrame->Dr0, TrapFrame->Dr1, TrapFrame->Dr2, TrapFrame->Dr3, TrapFrame->Dr6, TrapFrame->Dr7, TrapFrame->Cr2, TrapFrame->Cr3, TrapFrame->SegCs, TrapFrame->SegDs, TrapFrame->SegEs, TrapFrame->SegFs, TrapFrame->SegGs, TrapFrame->SegSs); /* Check vector and call appropriate handler */ switch(TrapFrame->Vector) { case 0x00: /* Divide By Zero exception */ HandleTrap00(TrapFrame); break; case 0x01: /* Debug exception */ HandleTrap01(TrapFrame); break; case 0x02: /* Non-Maskable Interrupt (NMI) */ HandleTrap02(TrapFrame); break; case 0x03: /* INT3 instruction executed */ HandleTrap03(TrapFrame); break; case 0x04: /* Overflow exception */ HandleTrap04(TrapFrame); break; case 0x05: /* Bound Range Exceeded exception */ HandleTrap05(TrapFrame); break; case 0x06: /* Invalid Opcode exception */ HandleTrap06(TrapFrame); break; case 0x07: /* Device Not Available exception */ HandleTrap07(TrapFrame); break; case 0x08: /* Double Fault exception */ HandleTrap08(TrapFrame); break; case 0x09: /* Segment Overrun exception */ HandleTrap09(TrapFrame); break; case 0x0A: /* Invalid TSS exception */ HandleTrap0A(TrapFrame); break; case 0x0B: /* Segment Not Present exception */ HandleTrap0B(TrapFrame); break; case 0x0C: /* Stack Segment Fault exception */ HandleTrap0C(TrapFrame); break; case 0x0D: /* General Protection Fault (GPF) exception*/ HandleTrap0D(TrapFrame); break; case 0x0E: /* Page Fault exception */ HandleTrap0E(TrapFrame); break; case 0x10: /* X87 Floating-Point exception */ HandleTrap10(TrapFrame); break; case 0x11: /* Alignment Check exception */ HandleTrap11(TrapFrame); break; case 0x12: /* Machine Check exception */ HandleTrap12(TrapFrame); break; case 0x13: /* SIMD Floating-Point exception */ HandleTrap13(TrapFrame); break; case 0x2A: /* Tick Count service request */ HandleTrap2A(TrapFrame); break; case 0x2B: /* User-mode callback return */ HandleTrap2B(TrapFrame); break; case 0x2C: /* Assertion raised */ HandleTrap2C(TrapFrame); break; case 0x2D: /* Debug-Service-Request raised */ HandleTrap2D(TrapFrame); break; case 0x2E: /* System call service request */ HandleTrap2E(TrapFrame); break; default: /* Unknown/Unexpected trap */ HandleTrapFF(TrapFrame); break; } } /** * Handles the trap 0x00 when a Divide By Zero exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap00(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Division-By-Zero Error (0x00)!\n"); KE::Crash::Panic(0x00); } /** * Handles the trap 0x01 when Debug exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap01(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Debug exception (0x01)!\n"); KE::Crash::Panic(0x01); } /** * Handles the trap 0x02 when Non-Maskable Interrupt (NMI) occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap02(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Non-Maskable-Interrupt (0x02)!\n"); } /** * Handles the trap 0x03 when the INT3 instruction is executed. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap03(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled INT3 (0x03)!\n"); KE::Crash::Panic(0x03); } /** * Handles the trap 0x04 when the INTO instruction is executed and overflow bit is set. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap04(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Overflow exception (0x04)!\n"); KE::Crash::Panic(0x04); } /** * Handles the trap 0x05 when the Bound Range Exceeded exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap05(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Bound-Range-Exceeded exception (0x05)!\n"); KE::Crash::Panic(0x05); } /** * Handles the trap 0x06 when the Invalid Opcode exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap06(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Invalid Opcode exception (0x06)!\n"); KE::Crash::Panic(0x06); } /** * Handles the trap 0x07 when the Device Not Available exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap07(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Device Not Available exception (0x07)!\n"); KE::Crash::Panic(0x07); } /** * Handles the trap 0x08 when Double Fault exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap08(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Double-Fault exception (0x08)!\n"); KE::Crash::Panic(0x08); } /** * Handles the trap 0x09 when the Segment Overrun exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap09(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Segment-Overrun exception (0x09)!\n"); KE::Crash::Panic(0x09); } /** * Handles the trap 0x0A when the Invalid TSS exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap0A(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Invalid-TSS exception (0x0A)!\n"); KE::Crash::Panic(0x0A); } /** * Handles the trap 0x0B when the Segment Not Present exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap0B(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Segment-Not-Present exception (0x0B)!\n"); KE::Crash::Panic(0x0B); } /** * Handles the trap 0x0C when the Stack Segment Fault exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap0C(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Stack-Segment-Fault exception (0x0C)!\n"); KE::Crash::Panic(0x0C); } /** * Handles the trap 0x0D when General Protection Fault (GPF) exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap0D(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled General-Protection-Fault (0x0D)!\n"); KE::Crash::Panic(0x0D); } /** * Handles the trap 0x0E when the Page Fault (PF) exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap0E(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Page-Fault exception (0x0E)!\n"); KE::Crash::Panic(0x0E); } /** * Handles the trap 0x10 when the X87 Floating-Point exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap10(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled x87 Floating-Point exception (0x10)!\n"); KE::Crash::Panic(0x10); } /** * Handles the trap 0x11 when the Alignment Check exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap11(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Alignment-Check exception (0x11)!\n"); KE::Crash::Panic(0x11); } /** * Handles the trap 0x12 when the Machine Check exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap12(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Machine-Check exception (0x12)!\n"); KE::Crash::Panic(0x12); } /** * Handles the trap 0x13 when the SIMD Floating-Point exception occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap13(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled SIMD Floating-Point exception (0x13)!\n"); KE::Crash::Panic(0x13); } /** * Handles the trap 0x2A when Tick Count service request occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap2A(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Unhandled Tick Count service request (0x2A)!\n"); } /** * Handles the trap 0x2B when Callback return service request occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap2B(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Unhandled Callback return service request (0x2B)!\n"); } /** * Handles the trap 0x2C when an assertion is raised. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap2C(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Assertion (0x2C)!\n"); KE::Crash::Panic(0x2C); } /** * Handles the trap 0x2D when a debug service is being requested. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap2D(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Debug-Service-Request (0x2D)!\n"); KE::Crash::Panic(0x2D); } /** * Handles the trap 0x2E when a system call is being requested. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrap2E(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Unhandled system call (0x2E)!\n"); } /** * Handles the trap 0xFF then Unexpected Interrupt occurs. * * @param TrapFrame * Supplies a kernel trap frame pushed by common trap handler on the stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::HandleTrapFF(IN PKTRAP_FRAME TrapFrame) { DebugPrint(L"Handled Unexpected-Interrupt (0xFF)!\n"); KE::Crash::Panic(0xFF); } /** * Sets the unhandled interrupt routine used for vectors that have no handler registered. * * @param Handler * Supplies the pointer to the interrupt handler routine. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID AR::Traps::SetUnhandledInterruptRoutine(PINTERRUPT_HANDLER Handler) { /* Set the unhandled interrupt routine */ UnhandledInterruptRoutine = Handler; } ================================================ FILE: xtoskrnl/ex/exports.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ex/exports.cc * DESCRIPTION: C-compatible API wrappers for exported kernel functions * DEVELOPERS: Aiken Harris */ #include /** * Acquires the rundown protection for given descriptor. * * @param Descriptor * Supplies a pointer to the rundown block descriptor. * * @return This routine returns TRUE if protection acquired successfully, or FALSE otherwise. * * @since NT 5.1 */ XTFASTCALL BOOLEAN ExAcquireRundownProtection(IN PEX_RUNDOWN_REFERENCE Descriptor) { return EX::Rundown::AcquireProtection(Descriptor); } /** * Marks the rundown descriptor as completed. * * @param Descriptor * Supplies a pointer to the descriptor to be completed. * * @return This routine does not return any value. * * @since NT 5.1 */ XTFASTCALL VOID ExCompleteRundownProtection(IN PEX_RUNDOWN_REFERENCE Descriptor) { EX::Rundown::CompleteProtection(Descriptor); } /** * Initializes the rundown protection descriptor. * * @param Descriptor * Supplies a pointer to the descriptor to be initialized. * * @return This routine does not return any value. * * @since NT 5.1 */ XTFASTCALL VOID ExInitializeRundownProtection(IN PEX_RUNDOWN_REFERENCE Descriptor) { EX::Rundown::InitializeProtection(Descriptor); } /** * Reinitializes the rundown protection structure after it has been completed. * * @param Descriptor * Supplies a pointer to the descriptor to be reinitialized. * * @return This routine does not return any value. * * @since NT 5.1 */ XTFASTCALL VOID ExReInitializeRundownProtection(IN PEX_RUNDOWN_REFERENCE Descriptor) { EX::Rundown::ReInitializeProtection(Descriptor); } /** * Releases the rundown protection for given descriptor. * * @param Descriptor * Supplies a pointer to the descriptor to be initialized. * * @return This routine does not return any value. * * @since NT 5.1 */ XTFASTCALL VOID ExReleaseRundownProtection(IN PEX_RUNDOWN_REFERENCE Descriptor) { EX::Rundown::ReleaseProtection(Descriptor); } /** * Waits until rundown protection calls are completed. * * @param Descriptor * Supplies a pointer to the rundown block descriptor. * * @return This routine does not return any value. * * @since NT 5.1 */ XTFASTCALL VOID ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REFERENCE Descriptor) { EX::Rundown::WaitForProtectionRelease(Descriptor); } ================================================ FILE: xtoskrnl/ex/rundown.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ex/rundown.cc * DESCRIPTION: Rundown protection mechanism * DEVELOPERS: Rafal Kupiec */ #include /** * Acquires the rundown protection for given descriptor. * * @param Descriptor * Supplies a pointer to the rundown block descriptor. * * @return This routine returns TRUE if protection acquired successfully, or FALSE otherwise. * * @since XT 1.0 */ XTFASTCALL BOOLEAN EX::Rundown::AcquireProtection(IN PEX_RUNDOWN_REFERENCE Descriptor) { ULONG_PTR CurrentValue, NewValue; /* Get current value */ CurrentValue = Descriptor->Count; /* Main loop execution */ while(TRUE) { /* Make sure protection is not active yet */ if(CurrentValue & 0x1) { /* Already active, nothing to do */ return FALSE; } /* Attempt to increment the usage count */ NewValue = CurrentValue + 2; /* Exchange the value */ NewValue = (ULONG_PTR)RTL::Atomic::CompareExchangePointer(&Descriptor->Ptr, (PVOID)NewValue, (PVOID)CurrentValue); /* Make sure protection acquired */ if(NewValue == CurrentValue) { /* Successfully acquired protection */ return TRUE; } /* Update value and try once again */ CurrentValue = NewValue; } } /** * Marks the rundown descriptor as completed. * * @param Descriptor * Supplies a pointer to the descriptor to be completed. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID EX::Rundown::CompleteProtection(IN PEX_RUNDOWN_REFERENCE Descriptor) { RTL::Atomic::ExchangePointer(&Descriptor->Ptr, (PVOID)EX_RUNDOWN_ACTIVE); } /** * Initializes the rundown protection descriptor. * * @param Descriptor * Supplies a pointer to the descriptor to be initialized. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID EX::Rundown::InitializeProtection(IN PEX_RUNDOWN_REFERENCE Descriptor) { /* Reset descriptor counter */ Descriptor->Count = 0; } /** * Reinitializes the rundown protection structure after it has been completed. * * @param Descriptor * Supplies a pointer to the descriptor to be reinitialized. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID EX::Rundown::ReInitializeProtection(IN PEX_RUNDOWN_REFERENCE Descriptor) { RTL::Atomic::ExchangePointer(&Descriptor->Ptr, NULLPTR); } /** * Releases the rundown protection for given descriptor. * * @param Descriptor * Supplies a pointer to the descriptor to be initialized. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID EX::Rundown::ReleaseProtection(IN PEX_RUNDOWN_REFERENCE Descriptor) { ULONG_PTR CurrentValue, NewValue; PEX_RUNDOWN_WAIT_BLOCK WaitBlock; CurrentValue = Descriptor->Count; while(TRUE) { if(CurrentValue & 0x1) { WaitBlock = (PEX_RUNDOWN_WAIT_BLOCK)(CurrentValue & ~0x1); if(!RTL::Atomic::Decrement64((PLONG_PTR)&WaitBlock->Count)) { KE::Event::SetEvent(&WaitBlock->WakeEvent, 0, FALSE); } break; } else { /* Attempt to decrement the usage count */ NewValue = CurrentValue - 2; /* Exchange the value */ NewValue = (ULONG_PTR)RTL::Atomic::CompareExchangePointer(&Descriptor->Ptr, (PVOID)NewValue, (PVOID)CurrentValue); if(NewValue == CurrentValue) { break; } CurrentValue = NewValue; } } } /** * Waits until rundown protection calls are completed. * * @param Descriptor * Supplies a pointer to the rundown block descriptor. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID EX::Rundown::WaitForProtectionRelease(IN PEX_RUNDOWN_REFERENCE Descriptor) { UNIMPLEMENTED; } ================================================ FILE: xtoskrnl/hl/acpi.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/x86/acpi.cc * DESCRIPTION: Advanced Configuration and Power Interface (ACPI) support * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Stores given ACPI table in the kernel local cache. * * @param AcpiTable * Supplies a pointer to ACPI table that will be stored in the cache. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Acpi::CacheAcpiTable(IN PACPI_DESCRIPTION_HEADER AcpiTable) { PACPI_CACHE_LIST AcpiCache; /* Check if there are free slots in static early-boot cache array */ if(CacheCount >= ACPI_MAX_CACHED_TABLES) { /* Cache is full, the table is mapped but not cached */ return; } /* Get the next available static cache entry */ AcpiCache = &CacheEntries[CacheCount]; CacheCount++; /* Store the pointer to the mapped ACPI table */ AcpiCache->Table = AcpiTable; /* Insert entry into the global ACPI cache list */ RTL::LinkedList::InsertTailList(&CacheList, &AcpiCache->ListEntry); } /** * Gets a pointer to the ACPI system description pointer (RSDP). * * @param Rsdp * Supplies a pointer to the memory area, where RSDP virtual address will be stored. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Acpi::GetAcpiSystemDescriptionPointer(OUT PACPI_RSDP *Rsdp) { /* Get RSDP and return success */ *Rsdp = RsdpStructure; return STATUS_SUCCESS; } /** * Gets an ACPI description table with given signature, available in the XSDT/RSDT. * * @param Signature * Supplies the signature of the desired ACPI table. * * @param AcpiTable * Supplies a pointer to memory area where ACPI table virtual address will be stored. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Acpi::GetAcpiTable(IN ULONG Signature, OUT PACPI_DESCRIPTION_HEADER *AcpiTable) { PACPI_DESCRIPTION_HEADER Table; XTSTATUS Status; /* Assume ACPI table not found */ *AcpiTable = NULLPTR; /* Attempt to get ACPI table from the cache */ Status = QueryAcpiCache(Signature, &Table); if(Status != STATUS_SUCCESS) { /* Table not found in the cache, query ACPI tables */ Status = QueryAcpiTables(Signature, &Table); if(Status != STATUS_SUCCESS) { /* ACPI table not found, return error */ return STATUS_NOT_FOUND; } } /* Store ACPI table and return success */ *AcpiTable = Table; return STATUS_SUCCESS; } /** * Retrieves the ACPI timer information. * * @param AcpiTimerInfo * Supplies a pointer to memory area, where ACPI timer information will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Acpi::GetAcpiTimerInfo(OUT PACPI_TIMER_INFO *AcpiTimerInfo) { /* Check if ACPI timer info is available */ if(AcpiTimerInfo) { /* Return ACPI timer info */ *AcpiTimerInfo = &TimerInfo; } } /** * Gets the ACPI system information structure containing processor and topology data. * * @param SystemInfo * Supplies a pointer to the memory area where the pointer to the system information structure will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Acpi::GetSystemInformation(OUT PACPI_SYSTEM_INFO *SystemInfo) { /* Return a pointer to the ACPI system information */ *SystemInfo = &HL::Acpi::SystemInfo; } /** * Performs an initialization of the ACPI subsystem. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Acpi::InitializeAcpi(VOID) { PACPI_FADT Fadt; XTSTATUS Status; /* Initialize ACPI cache */ Status = InitializeAcpiCache(); if(Status != STATUS_SUCCESS) { /* ACPI cache initialization failed, return error */ return Status; } /* Get Fixed ACPI Description Table (FADT) */ Status = GetAcpiTable(ACPI_FADT_SIGNATURE, (PACPI_DESCRIPTION_HEADER*)&Fadt); if(Status != STATUS_SUCCESS || !Fadt) { /* Failed to get FADT, return error */ return STATUS_NOT_FOUND; } /* Initialize ACPI timer */ InitializeAcpiTimer(); /* Return success */ return STATUS_SUCCESS; } /** * Initializes the kernel's local ACPI cache storage. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Acpi::InitializeAcpiCache(VOID) { PACPI_DESCRIPTION_HEADER Rsdt; XTSTATUS Status; /* Initialize ACPI cache list */ RTL::LinkedList::InitializeListHead(&CacheList); /* Get XSDT/RSDT */ Status = InitializeAcpiSystemDescriptionTable(&Rsdt); if(Status != STATUS_SUCCESS) { /* Failed to get XSDT/RSDT, return error */ return Status; } /* Cache XSDT/RSDT table */ CacheAcpiTable(Rsdt); /* Return success */ return STATUS_SUCCESS; } /** * Initializes ACPI System Description Table (XSDT/RSDT) by finding proper table and mapping its virtual address. * * @param AcpiTable * Supplies a pointer to memory area where ACPI table virtual address will be stored. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Acpi::InitializeAcpiSystemDescriptionTable(OUT PACPI_DESCRIPTION_HEADER *AcpiTable) { PHYSICAL_ADDRESS RsdpAddress, RsdtAddress; PSYSTEM_RESOURCE_HEADER ResourceHeader; PSYSTEM_RESOURCE_ACPI AcpiResource; ULONG RsdtPages; PACPI_RSDT Rsdt; XTSTATUS Status; /* Assume ACPI table not found */ *AcpiTable = NULLPTR; /* Get ACPI system resource */ Status = KeGetSystemResource(SystemResourceAcpi, &ResourceHeader); if(Status != STATUS_SUCCESS) { /* Resource not found */ return STATUS_NOT_FOUND; } /* Cast system resource to ACPI resource and store RSDP physical address */ AcpiResource = (PSYSTEM_RESOURCE_ACPI)ResourceHeader; RsdpAddress.QuadPart = (LONGLONG)AcpiResource->Header.PhysicalAddress; /* Map RSDP using hardware memory pool */ Status = MM::HardwarePool::MapHardwareMemory(RsdpAddress, 1, TRUE, (PVOID *)&RsdpStructure); if(Status != STATUS_SUCCESS) { /* Failed to map RSDP, return error */ return Status; } /* Mark RSDP as CD/WT to avoid delays in write-back cache */ MM::HardwarePool::MarkHardwareMemoryWriteThrough(RsdpStructure, 1); /* Validate RSDP signature */ if(RsdpStructure->Signature != ACPI_RSDP_SIGNATURE) { /* Invalid RSDP signature, unmap and return error */ MM::HardwarePool::UnmapHardwareMemory(RsdpStructure, 1, TRUE); RsdpStructure = NULLPTR; return STATUS_INVALID_PARAMETER; } /* Check RSDP revision to determine RSDT/XSDT address */ if(RsdpStructure->Revision >= 2) { /* Get XSDT address */ RsdtAddress.QuadPart = (LONGLONG)RsdpStructure->XsdtAddress; } else { /* Get RSDT address */ RsdtAddress.QuadPart = (LONGLONG)RsdpStructure->RsdtAddress; } /* Map RSDT/XSDT using hardware memory pool */ Status = MM::HardwarePool::MapHardwareMemory(RsdtAddress, 2, TRUE, (PVOID *)&Rsdt); if(Status != STATUS_SUCCESS) { /* Failed to map RSDT/XSDT, return error */ return Status; } /* Mark RSDT/XSDT as CD/WT */ MM::HardwarePool::MarkHardwareMemoryWriteThrough(Rsdt, 2); /* Validate RSDT/XSDT signature */ if(Rsdt->Header.Signature != ACPI_RSDT_SIGNATURE && Rsdt->Header.Signature != ACPI_XSDT_SIGNATURE) { /* Not mapped correctly or invalid RSDT/XSDT signature, unmap and return error */ MM::HardwarePool::UnmapHardwareMemory(Rsdt, 2, TRUE); return STATUS_INVALID_PARAMETER; } /* Calculate the length of all available ACPI tables and remap it if needed */ RsdtPages = (((RsdtAddress.LowPart & (MM_PAGE_SIZE - 1)) + Rsdt->Header.Length + (MM_PAGE_SIZE - 1)) >> MM_PAGE_SHIFT); if(RsdtPages != 2) { /* RSDT/XSDT needs less or more than 2 pages, remap it */ MM::HardwarePool::UnmapHardwareMemory(Rsdt, 2, TRUE); Status = MM::HardwarePool::MapHardwareMemory(RsdtAddress, RsdtPages, TRUE, (PVOID *)&Rsdt); if(Status != STATUS_SUCCESS) { /* Remapping failed, return error */ return STATUS_INSUFFICIENT_RESOURCES; } /* Mark remapped RSDT/XSDT as CD/WT */ MM::HardwarePool::MarkHardwareMemoryWriteThrough(Rsdt, RsdtPages); } /* Get ACPI table header and return success */ *AcpiTable = &Rsdt->Header; return STATUS_SUCCESS; } /** * Initializes System Information structure based on the ACPI provided data. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Acpi::InitializeAcpiSystemInformation(VOID) { PACPI_MADT_LOCAL_X2APIC LocalX2Apic; PACPI_MADT_LOCAL_APIC LocalApic; PACPI_SUBTABLE_HEADER SubTable; ULONG_PTR MadtTable; PACPI_MADT Madt; XTSTATUS Status; USHORT CpuCount; /* Allocate memory for ACPI system information structure */ Status = InitializeAcpiSystemStructure(); if(Status != STATUS_SUCCESS) { /* Failed to allocate memory, return error */ return STATUS_INSUFFICIENT_RESOURCES; } /* Get Multiple APIC Description Table (MADT) */ Status = GetAcpiTable(ACPI_MADT_SIGNATURE, (PACPI_DESCRIPTION_HEADER*)&Madt); if(Status != STATUS_SUCCESS) { /* Failed to get MADT, return error */ return STATUS_NOT_FOUND; } /* Set APIC table traverse pointer and initialize number of CPUs */ MadtTable = (ULONG_PTR)Madt->ApicTables; CpuCount = 0; /* Traverse all MADT tables to get system information */ while(MadtTable < ((ULONG_PTR)Madt + Madt->Header.Length)) { /* Get current MADT subtable header */ SubTable = (PACPI_SUBTABLE_HEADER)MadtTable; /* Prevent infinite loops if BIOS provides 0 length */ if(SubTable->Length == 0) { /* Broken ACPI table, abort traversal */ break; } /* Check if this is a local APIC subtable */ if(SubTable->Type == ACPI_MADT_TYPE_LOCAL_APIC && SubTable->Length >= sizeof(ACPI_MADT_LOCAL_APIC)) { /* Get local APIC subtable */ LocalApic = (PACPI_MADT_LOCAL_APIC)MadtTable; /* Make sure, this CPU can be enabled */ if(LocalApic->Flags & ACPI_MADT_PLAOC_ENABLED) { /* Store CPU number, APIC ID and CPU ID */ SystemInfo.CpuInfo[CpuCount].AcpiId = LocalApic->AcpiId; SystemInfo.CpuInfo[CpuCount].ApicId = LocalApic->ApicId; SystemInfo.CpuInfo[CpuCount].CpuNumber = CpuCount; /* Increment number of CPUs */ CpuCount++; } } else if(SubTable->Type == ACPI_MADT_TYPE_LOCAL_X2APIC && SubTable->Length >= sizeof(ACPI_MADT_LOCAL_X2APIC)) { /* Get local X2APIC subtable */ LocalX2Apic = (PACPI_MADT_LOCAL_X2APIC)MadtTable; /* Make sure, this CPU can be enabled */ if(LocalX2Apic->Flags & ACPI_MADT_PLAOC_ENABLED) { /* Store CPU number, APIC ID and CPU ID */ SystemInfo.CpuInfo[CpuCount].AcpiId = LocalX2Apic->AcpiId; SystemInfo.CpuInfo[CpuCount].ApicId = LocalX2Apic->ApicId; SystemInfo.CpuInfo[CpuCount].CpuNumber = CpuCount; /* Increment number of CPUs */ CpuCount++; } } /* Safely advance pointer using proper subtable length */ MadtTable += SubTable->Length; } /* Store number of CPUs */ SystemInfo.CpuCount = CpuCount; /* Return success */ return STATUS_SUCCESS; } /** * Initializes ACPI System Information data structure based on the size of available ACPI data. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Acpi::InitializeAcpiSystemStructure(VOID) { PHYSICAL_ADDRESS PhysicalAddress; PACPI_SUBTABLE_HEADER SubTable; PFN_NUMBER PageCount; ULONG_PTR MadtTable; PACPI_MADT Madt; XTSTATUS Status; ULONG CpuCount; /* Get Multiple APIC Description Table (MADT) */ Status = GetAcpiTable(ACPI_MADT_SIGNATURE, (PACPI_DESCRIPTION_HEADER*)&Madt); if(Status != STATUS_SUCCESS) { /* Failed to get MADT, return error */ return STATUS_NOT_FOUND; } /* Set APIC table traverse pointer and initialize number of CPUs */ MadtTable = (ULONG_PTR)Madt->ApicTables; CpuCount = 0; /* Traverse all MADT tables to get number of processors */ while(MadtTable < ((ULONG_PTR)Madt + Madt->Header.Length)) { SubTable = (PACPI_SUBTABLE_HEADER)MadtTable; /* Prevent infinite loops if BIOS provides 0 length */ if(SubTable->Length == 0) { /* Broken ACPI table, abort traversal */ break; } /* Check if this is a local APIC subtable */ if(SubTable->Type == ACPI_MADT_TYPE_LOCAL_APIC && SubTable->Length >= sizeof(ACPI_MADT_LOCAL_APIC)) { /* Make sure, this CPU can be enabled */ if(((PACPI_MADT_LOCAL_APIC)MadtTable)->Flags & ACPI_MADT_PLAOC_ENABLED) { /* Increment number of CPUs */ CpuCount++; } } else if(SubTable->Type == ACPI_MADT_TYPE_LOCAL_X2APIC && SubTable->Length >= sizeof(ACPI_MADT_LOCAL_X2APIC)) { /* Make sure, this CPU can be enabled */ if(((PACPI_MADT_LOCAL_X2APIC)MadtTable)->Flags & ACPI_MADT_PLAOC_ENABLED) { /* Increment number of CPUs */ CpuCount++; } } /* Safely advance pointer using proper subtable length */ MadtTable += SubTable->Length; } /* Zero the ACPI system information structure */ RTL::Memory::ZeroMemory(&SystemInfo, sizeof(ACPI_SYSTEM_INFO)); /* Calculate number of pages needed to store CPU information */ PageCount = SIZE_TO_PAGES(CpuCount * sizeof(PROCESSOR_IDENTITY)); /* Allocate memory for CPU information */ Status = MM::HardwarePool::AllocateHardwareMemory(PageCount, TRUE, MM_MAXIMUM_PHYSICAL_ADDRESS, &PhysicalAddress); if(Status != STATUS_SUCCESS) { /* Failed to allocate memory, return error */ return Status; } /* Map physical address to the virtual memory area */ Status = MM::HardwarePool::MapHardwareMemory(PhysicalAddress, PageCount, TRUE, (PVOID *)&SystemInfo.CpuInfo); if(Status != STATUS_SUCCESS) { /* Failed to map memory, return error */ return Status; } /* Zero the CPU information structure */ RTL::Memory::ZeroMemory(SystemInfo.CpuInfo, PAGES_TO_SIZE(PageCount)); /* Return success */ return STATUS_SUCCESS; } /** * Initializes the ACPI Timer. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Acpi::InitializeAcpiTimer(VOID) { PACPI_FADT Fadt; XTSTATUS Status; /* Get Fixed ACPI Description Table (FADT) */ Status = GetAcpiTable(ACPI_FADT_SIGNATURE, (PACPI_DESCRIPTION_HEADER*)&Fadt); if(Status != STATUS_SUCCESS || !Fadt) { /* Failed to get FADT, return error */ return STATUS_NOT_FOUND; } /* Set ACPI timer port address */ TimerInfo.TimerPort = Fadt->PmTmrBlkIoPort; /* Determine whether 32-bit or 24-bit timer is used */ if(Fadt->Flags & ACPI_FADT_32BIT_TIMER) { /* 32-bit timer */ TimerInfo.MsbMask = ACPI_FADT_TIMER_32BIT; } else { /* 24-bit timer */ TimerInfo.MsbMask = ACPI_FADT_TIMER_24BIT; } /* Return success */ return STATUS_SUCCESS; } /** * Queries kernel local ACPI cache in attempt to find a requested ACPI table. * * @param Signature * Supplies the signature of the desired ACPI table. * * @param AcpiTable * Supplies a pointer to memory area where ACPI table virtual address will be stored. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Acpi::QueryAcpiCache(IN ULONG Signature, OUT PACPI_DESCRIPTION_HEADER *AcpiTable) { PACPI_DESCRIPTION_HEADER TableHeader; PACPI_CACHE_LIST AcpiCache; PLIST_ENTRY ListEntry; /* Initialize variables */ TableHeader = NULLPTR; /* Iterate through ACPI tables cache list */ ListEntry = CacheList.Flink; while(ListEntry != &CacheList) { /* Get cached ACPI table header */ AcpiCache = CONTAIN_RECORD(ListEntry, ACPI_CACHE_LIST, ListEntry); /* Check if ACPI table signature matches */ if(AcpiCache->Table->Signature == Signature) { /* ACPI table found in cache, return it */ TableHeader = AcpiCache->Table; break; } /* Go to the next cache entry */ ListEntry = ListEntry->Flink; } /* Check if the requested ACPI table was found in the cache */ if(TableHeader == NULLPTR) { /* ACPI table not found in cache, return error */ return STATUS_NOT_FOUND; } /* Return table header and status code */ *AcpiTable = TableHeader; return STATUS_SUCCESS; } /** * Queries XSDT/RSDT in order to find a requested ACPI table. * Once the desired ACPI table is found, it is being mapped and cached. * * @param Signature * Supplies the signature of the desired ACPI table. * * @param AcpiTable * Supplies a pointer to memory area where ACPI table virtual address will be stored. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Acpi::QueryAcpiTables(IN ULONG Signature, OUT PACPI_DESCRIPTION_HEADER *AcpiTable) { ULONG TableCount, TableIndex, TablePages; PACPI_DESCRIPTION_HEADER TableHeader; PHYSICAL_ADDRESS TableAddress; PACPI_FADT Fadt; PACPI_RSDT Rsdt; PACPI_XSDT Xsdt; XTSTATUS Status; /* Check if requesting a valid ACPI table */ if(Signature == ACPI_RSDT_SIGNATURE || Signature == ACPI_XSDT_SIGNATURE) { /* Cannot provide RSDP/XSDP table, it should be cached; return error */ return STATUS_INVALID_PARAMETER; } /* Ensure that table header is not set before attempting to find ACPI table */ TableHeader = NULLPTR; /* Check if DSDT or FACS table requested */ if(Signature == ACPI_DSDT_SIGNATURE || Signature == ACPI_FACS_SIGNATURE) { /* Get FADT as it contains a pointer to DSDT and FACS */ Status = GetAcpiTable(ACPI_FADT_SIGNATURE, (PACPI_DESCRIPTION_HEADER*)&Fadt); if(Status != STATUS_SUCCESS) { /* Failed to get FADT, return error */ return Status; } /* Check if DSDT or FACS table requested */ if(Signature == ACPI_DSDT_SIGNATURE) { /* Prefer 64-bit address on ACPI 2.0+ */ if(Fadt->Header.Revision >= 2 && Fadt->XDsdt.QuadPart != 0) { TableAddress.QuadPart = Fadt->XDsdt.QuadPart; } else { TableAddress.LowPart = Fadt->Dsdt; TableAddress.HighPart = 0; } } else { /* Prefer 64-bit address on ACPI 2.0+ */ if(Fadt->Header.Revision >= 2 && Fadt->XFirmwareCtrl.QuadPart != 0) { TableAddress.QuadPart = Fadt->XFirmwareCtrl.QuadPart; } else { TableAddress.LowPart = Fadt->FirmwareCtrl; TableAddress.HighPart = 0; } } /* Map table using hardware memory pool */ Status = MM::HardwarePool::MapHardwareMemory(TableAddress, 2, TRUE, (PVOID*)&TableHeader); if(Status != STATUS_SUCCESS) { /* Failed to map table, return error */ return Status; } } else { /* Query cache for XSDT table */ Status = QueryAcpiCache(ACPI_XSDT_SIGNATURE, (PACPI_DESCRIPTION_HEADER*)&Xsdt); if(Status != STATUS_SUCCESS) { /* XSDT not found, query cache for RSDT table */ Xsdt = NULLPTR; Status = QueryAcpiCache(ACPI_RSDT_SIGNATURE, (PACPI_DESCRIPTION_HEADER*)&Rsdt); } /* Check if XSDT or RSDT table found */ if(Status != STATUS_SUCCESS) { /* Failed to get XSDT/RSDT, return error */ return Status; } /* Get table count depending on root table type securely */ if(Xsdt != NULLPTR) { if(Xsdt->Header.Length < sizeof(ACPI_DESCRIPTION_HEADER)) return STATUS_INVALID_PARAMETER; TableCount = (Xsdt->Header.Length - sizeof(ACPI_DESCRIPTION_HEADER)) / 8; } else { if(Rsdt->Header.Length < sizeof(ACPI_DESCRIPTION_HEADER)) return STATUS_INVALID_PARAMETER; TableCount = (Rsdt->Header.Length - sizeof(ACPI_DESCRIPTION_HEADER)) / 4; } /* Iterate over all ACPI tables */ for(TableIndex = 0; TableIndex < TableCount; TableIndex++) { /* Check if XSDT or RSDT is used */ if(Xsdt != NULLPTR) { /* Get table header physical address from XSDT */ TableAddress.QuadPart = Xsdt->Tables[TableIndex]; } else { /* Get table header physical address from RSDT */ TableAddress.LowPart = Rsdt->Tables[TableIndex]; TableAddress.HighPart = 0; } /* Map table using hardware memory pool */ Status = MM::HardwarePool::MapHardwareMemory(TableAddress, 2, TRUE, (PVOID*)&TableHeader); if(Status != STATUS_SUCCESS) { /* Failed to map table, return error */ return Status; } /* Verify table signature */ if(TableHeader->Signature == Signature) { /* Found requested ACPI table */ break; } /* Unmap non-matching table and try next one */ MM::HardwarePool::UnmapHardwareMemory(TableHeader, 2, TRUE); TableHeader = NULLPTR; } } /* Ensure the table was actually found and mapped */ if(TableHeader == NULLPTR) { /* ACPI table not found, return error */ return STATUS_NOT_FOUND; } /* Check if we broke out of the loop with the wrong table (safety check) */ if(TableHeader->Signature != Signature) { /* Unmap non-matching ACPI table and return error */ MM::HardwarePool::UnmapHardwareMemory(TableHeader, 2, TRUE); return STATUS_NOT_FOUND; } /* Don't validate FACS and FADT on old, broken firmwares with ACPI 2.0 or older */ if((TableHeader->Signature != ACPI_FADT_SIGNATURE || TableHeader->Revision > 2) && (TableHeader->Signature != ACPI_FACS_SIGNATURE)) { /* Validate table checksum */ if(!ValidateAcpiTable(TableHeader, TableHeader->Length)) { /* Checksum mismatch, unmap table and return error */ MM::HardwarePool::UnmapHardwareMemory(TableHeader, 2, TRUE); return STATUS_CRC_ERROR; } } /* Calculate the length of ACPI table and remap it if needed */ TablePages = (((TableAddress.LowPart & (MM_PAGE_SIZE - 1)) + TableHeader->Length + (MM_PAGE_SIZE - 1)) >> MM_PAGE_SHIFT); if(TablePages != 2) { /* ACPI table needs less or more than 2 pages, remap it */ MM::HardwarePool::UnmapHardwareMemory(TableHeader, 2, FALSE); Status = MM::HardwarePool::MapHardwareMemory(TableAddress, TablePages, TRUE, (PVOID*)&TableHeader); /* Make sure remapping was successful */ if(Status != STATUS_SUCCESS) { /* Remapping failed, return error */ return STATUS_INSUFFICIENT_RESOURCES; } } /* Mark table as write through and store it in local cache */ MM::HardwarePool::MarkHardwareMemoryWriteThrough(TableHeader, TablePages); CacheAcpiTable(TableHeader); /* Store ACPI table and return success */ *AcpiTable = TableHeader; return STATUS_SUCCESS; } /** * Validates given ACPI table by calculating its checksum. * * @param Buffer * Supplies a pointer to the table to checksum. * * @param Size * Supplies the size of the table, in bytes. * * @return This routine returns TRUE if the table is valid, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN HL::Acpi::ValidateAcpiTable(IN PVOID Buffer, IN UINT_PTR Size) { PUCHAR Pointer; UCHAR Sum; /* Initialize variables */ Sum = 0; Pointer = (PUCHAR)Buffer; /* Calculate checksum of given table */ while(Size != 0) { Sum = (UCHAR)(Sum + *Pointer); Pointer += 1; Size -= 1; } /* Return calculated checksum */ return (Sum == 0) ? TRUE : FALSE; } ================================================ FILE: xtoskrnl/hl/amd64/cpu.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/amd64/cpu.cc * DESCRIPTION: HAL AMD64 processor support * DEVELOPERS: Rafal Kupiec */ #include /* Include common CPU interface */ #include ARCH_COMMON(cpu.cc) ================================================ FILE: xtoskrnl/hl/amd64/firmware.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/amd64/firmware.cc * DESCRIPTION: UEFI/BIOS Firmware support * DEVELOPERS: Aiken Harris */ #include /* Include common Firmware interface */ #include ARCH_COMMON(firmware.cc) ================================================ FILE: xtoskrnl/hl/amd64/ioport.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/amd64/ioport.cc * DESCRIPTION: I/O port access routines for AMD64 platform * DEVELOPERS: Rafal Kupiec */ #include /** * Reads the 8-bit data from the specified I/O port. * * @param Port * Specifies the address to read from, in the range of 0-0xFFFF. * * @return This routine returns the value read from the port. * * @since XT 1.0 */ XTCDECL UCHAR HL::IoPort::ReadPort8(IN USHORT Port) { UCHAR Value; __asm__ volatile("inb %1, %0" : "=a" (Value) : "Nd" (Port)); return Value; } /** * Reads the 16-bit data from the specified I/O port. * * @param Port * Specifies the address to read from, in the range of 0-0xFFFF. * * @return This routine returns the value read from the port. * * @since XT 1.0 */ XTCDECL USHORT HL::IoPort::ReadPort16(IN USHORT Port) { USHORT Value; __asm__ volatile("inw %1, %0" : "=a" (Value) : "Nd" (Port)); return Value; } /** * Reads the 32-bit data from the specified I/O port. * * @param Port * Specifies the address to read from, in the range of 0-0xFFFF. * * @return This routine returns the value read from the port. * * @since XT 1.0 */ XTCDECL ULONG HL::IoPort::ReadPort32(IN USHORT Port) { ULONG Value; __asm__ volatile("inl %1, %0" : "=a" (Value) : "Nd" (Port)); return Value; } /** * Writes the 8-bit data to the specified I/O port. * * @param Port * Specifies the address to write to, in the range of 0-0xFFFF. * * @param Value * Supplies the value to write. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HL::IoPort::WritePort8(IN USHORT Port, IN UCHAR Value) { __asm__ volatile("outb %0, %1" : : "a" (Value), "Nd" (Port)); } /** * Writes the 16-bit data to the specified I/O port. * * @param Port * Specifies the address to write to, in the range of 0-0xFFFF. * * @param Value * Supplies the value to write. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HL::IoPort::WritePort16(IN USHORT Port, IN USHORT Value) { __asm__ volatile("outw %0, %1" : : "a" (Value), "Nd" (Port)); } /** * Writes the 32-bit data to the specified I/O port. * * @param Port * Specifies the address to write to, in the range of 0-0xFFFF. * * @param Value * Supplies the value to write. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HL::IoPort::WritePort32(IN USHORT Port, IN ULONG Value) { __asm__ volatile("outl %0, %1" : : "a" (Value), "Nd" (Port)); } ================================================ FILE: xtoskrnl/hl/amd64/irq.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/amd64/irq.cc * DESCRIPTION: Interrupts support for AMD64 architecture * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Begins a system interrupt handler by raising the processor's run level and re-enabling * hardware interrupts to allow preemption by higher-priority events. * * @param RunLevel * Supplies the target run level to raise the processor to. * * @param OldRunLevel * Receives the previous run level before the elevation. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Irq::BeginSystemInterrupt(IN KRUNLEVEL RunLevel, OUT PKRUNLEVEL OldRunLevel) { /* Get the current IRQL */ *OldRunLevel = KE::RunLevel::GetCurrentRunLevel(); /* Raise run level */ KE::RunLevel::RaiseRunLevel(RunLevel); /* Enable interrupts */ AR::CpuFunctions::SetInterruptFlag(); } /** * Safely concludes an interrupt handler by disabling hardware interrupts. * * @param TrapFrame * Supplies a pointer to the kernel trap frame containing the interrupted execution state. * * @param OldRunLevel * Supplies the previous run level to restore. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Irq::EndInterrupt(IN PKTRAP_FRAME TrapFrame, IN KRUNLEVEL OldRunLevel) { /* Disable interrupts */ AR::CpuFunctions::ClearInterruptFlag(); /* End system interrupt */ EndSystemInterrupt(TrapFrame, OldRunLevel); } /** * Concludes a system interrupt by sending an End of Interrupt (EOI) to the hardware * controller and restoring the processor's previous run level. * * @param TrapFrame * Supplies a pointer to the kernel trap frame containing the interrupted execution state. * * @param OldRunLevel * Supplies the previous run level to restore. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Irq::EndSystemInterrupt(IN PKTRAP_FRAME TrapFrame, IN KRUNLEVEL OldRunLevel) { /* Send EOI */ HL::Pic::SendEoi(); /* Restore previous run level */ KE::RunLevel::LowerRunLevel(OldRunLevel); } /** * Handles profiling interrupt. * * @param TrapFrame * Supplies a kernel trap frame pushed by common interrupt handler. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HL::Irq::HandleProfileInterrupt(IN PKTRAP_FRAME TrapFrame) { /* Send EOI */ HL::Pic::SendEoi(); } /** * Handles unexpected or unmapped system interrupts. * * @param TrapFrame * Supplies a kernel trap frame pushed by common interrupt handler. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HL::Irq::HandleUnexpectedInterrupt(IN PKTRAP_FRAME TrapFrame) { UNIMPLEMENTED; /* Disable interrupts */ AR::CpuFunctions::ClearInterruptFlag(); /* Print debug message and raise kernel panic */ DebugPrint(L"ERROR: Caught unexpected interrupt (0x%.2llX)!\n", TrapFrame->Vector); KE::Crash::Panic(0x47, TrapFrame->Vector, 0, 0, 0); } /** * Returns the registered interrupt handler for the specified IDT vector. * * @param Vector * Supplies the interrupt vector number. * * @return This routine returns the pointer to the IDT interrupt handler routine. * * @since XT 1.0 */ XTAPI PVOID HL::Irq::QueryInterruptHandler(IN ULONG Vector) { PKPROCESSOR_BLOCK ProcessorBlock; PKIDTENTRY IdtEntry; /* Get current processor block and IDT entry */ ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); IdtEntry = &ProcessorBlock->IdtBase[Vector]; /* Return address of the interrupt handler */ return (PVOID)((ULONGLONG)IdtEntry->OffsetHigh << 32 | (ULONGLONG)IdtEntry->OffsetMiddle << 16 | (ULONGLONG)IdtEntry->OffsetLow); } /** * Returns the registered interrupt handler for the specified vector. * * @param Vector * Supplies the interrupt vector number. * * @return This routine returns the pointer to the interrupt handler routine. * * @since XT 1.0 */ XTAPI PVOID HL::Irq::QuerySystemInterruptHandler(IN ULONG Vector) { PKPROCESSOR_BLOCK ProcessorBlock; /* Get current processor block */ ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); return (PVOID)ProcessorBlock->InterruptDispatchTable[Vector]; } /** * Registers new interrupt handler for the existing IDT entry. * * @param HalVector * Supplies the interrupt vector number. * * @param Handler * Supplies the pointer to the interrupt handler routine. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Irq::RegisterInterruptHandler(IN ULONG Vector, IN PVOID Handler) { PKPROCESSOR_BLOCK ProcessorBlock; /* Get current processor block */ ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); /* Update interrupt handler */ AR::ProcessorSupport::SetIdtGate(ProcessorBlock->IdtBase, Vector, Handler, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE); } /** * Registers the interrupt handler for the specified vector. * * @param HalVector * Supplies the interrupt vector number. * * @param Handler * Supplies the pointer to the interrupt handler routine. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Irq::RegisterSystemInterruptHandler(IN ULONG Vector, IN PINTERRUPT_HANDLER Handler) { PKPROCESSOR_BLOCK ProcessorBlock; /* Get current processor block */ ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); /* Update interrupt handler in the processor's interrupt dispatch table */ ProcessorBlock->InterruptDispatchTable[Vector] = Handler; } /** * Requests a software interrupt by sending a Self-IPI mapped to the specified run level. * * @param RunLevel * Supplies the target run level for the software interrupt. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID HL::Irq::SendSoftwareInterrupt(IN KRUNLEVEL RunLevel) { /* Request a software interrupt */ HL::Pic::SendSelfIpi(HL::RunLevel::TransformRunLevelToSoftwareVector(RunLevel)); } ================================================ FILE: xtoskrnl/hl/amd64/pic.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/amd64/pic.cc * DESCRIPTION: Programmable Interrupt Controller (PIC) for AMD64 support * DEVELOPERS: Rafal Kupiec */ #include /* Include common PIC interface */ #include ARCH_COMMON(pic.cc) ================================================ FILE: xtoskrnl/hl/amd64/rtc.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/amd64/rtc.cc * DESCRIPTION: Hardware Real-Time Clock (RTC) support * DEVELOPERS: Aiken Harris */ #include /* Include common RTC interface */ #include ARCH_COMMON(rtc.cc) ================================================ FILE: xtoskrnl/hl/amd64/runlevel.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/amd64/runlevel.cc * DESCRIPTION: Run Level management support for AMD64 architecture * DEVELOPERS: Rafal Kupiec */ #include /** * Gets the current run level from APIC for the current processor. * * @return This routine returns the current run level. * * @since XT 1.0 */ XTFASTCALL KRUNLEVEL HL::RunLevel::GetRunLevel(VOID) { /* Read current run level */ return (KRUNLEVEL)AR::CpuFunctions::ReadControlRegister(8); } /** * Sets new run level for the current processor. * * @param RunLevel * Supplies the new run level to store into APIC. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID HL::RunLevel::SetRunLevel(IN KRUNLEVEL RunLevel) { /* Set new run level */ AR::CpuFunctions::WriteControlRegister(8, RunLevel); } /** * Maps APIC interrupt vector to XT run level. * * @param Tpr * Supplies the interrupt vector rad from APIC Task Priority Register. * * @return This routine returns the XT run level corresponding to the specified APIC interrupt vector. * * @since XT 1.0 */ XTFASTCALL KRUNLEVEL HL::RunLevel::TransformApicTprToRunLevel(IN UCHAR Tpr) { /* Transform APIC TPR to run level */ return (KRUNLEVEL)(Tpr >> 4); } /** * Maps XT run level to interrupt vector suitable for the APIC Task Priority Register. * * @param RunLevel * Supplies the XT run level. * * @return This routine returns the APIC interrupt vector corresponding to the specified XT run level. * * @since XT 1.0 */ XTFASTCALL UCHAR HL::RunLevel::TransformRunLevelToApicTpr(IN KRUNLEVEL RunLevel) { /* Transform run level to APIC TPR */ return (RunLevel << 4); } /** * Transforms a given execution run level into a corresponding hardware interrupt vector * suitable for software interrupts. * * @param RunLevel * Supplies the run level to be translated into a software interrupt vector. * * @return This routine returns the 8-bit APIC vector corresponding to the requested software interrupt level. * * @since XT 1.0 */ XTFASTCALL UCHAR HL::RunLevel::TransformRunLevelToSoftwareVector(IN KRUNLEVEL RunLevel) { /* Transform run level to APIC interrupt vector */ return TransformRunLevelToApicTpr(RunLevel) | 0xF; } ================================================ FILE: xtoskrnl/hl/amd64/timer.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/amd64/timer.cc * DESCRIPTION: Timer support for AMD64 * DEVELOPERS: Aiken Harris */ #include /* Include common Timer interface */ #include ARCH_COMMON(timer.cc) ================================================ FILE: xtoskrnl/hl/cport.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/cport.cc * DESCRIPTION: Serial (COM) port support * DEVELOPERS: Rafal Kupiec */ #include /** * This routine gets a byte from serial port. * * @param Port * Address of port object describing a port settings. * * @param Byte * Address of variable where to store the result. * * @param Wait * Specifies whether to wait for a data or not. * * @param Poll * Indicates whether to only poll, not reading the data. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTCDECL XTSTATUS HL::ComPort::ReadComPort(IN PCPPORT Port, OUT PUCHAR Byte, IN BOOLEAN Wait, IN BOOLEAN Poll) { UCHAR Lsr; ULONG Retry; /* Make sure the port has been initialized */ if(Port->Address == 0) { return STATUS_DEVICE_NOT_READY; } /* Retry getting data if allowed to wait */ Retry = Wait ? COMPORT_WAIT_TIMEOUT : 1; while(Retry--) { /* Get LSR for data ready */ Lsr = ReadComPortLsr(Port, COMPORT_LSR_DR); if((Lsr & COMPORT_LSR_DR) == COMPORT_LSR_DR) { /* Check for errors */ if(Lsr & (COMPORT_LSR_FE | COMPORT_LSR_OE | COMPORT_LSR_PE)) { /* Framing, parity or overrun error occurred */ *Byte = 0; return STATUS_IO_DEVICE_ERROR; } /* Check if only polling */ if(Poll) { /* Only polling, return success */ return STATUS_SUCCESS; } /* Read the byte from serial port */ *Byte = HL::IoPort::ReadPort8(PtrToUshort(Port->Address + (ULONG)COMPORT_REG_RBR)); /* Check if in modem control mode */ if(Port->Flags & COMPORT_FLAG_MC) { /* Handle Carrier Detected (CD) */ if((HL::IoPort::ReadPort8(PtrToShort(Port->Address + (ULONG)COMPORT_REG_MSR)) & COMPORT_MSR_DCD) == 0) { /* Skip byte if no CD present */ continue; } } return STATUS_SUCCESS; } } /* Reset LSR and return that no data found */ ReadComPortLsr(Port, 0); return STATUS_NOT_FOUND; } /** * Reads LSR from specified serial port. * * @param Port * Address of COM port. * * @param Byte * Value expected from the port. * * @return This routine returns a byte read from COM port. * * @since XT 1.0 */ XTCDECL UCHAR HL::ComPort::ReadComPortLsr(IN PCPPORT Port, IN UCHAR Byte) { UCHAR Lsr, Msr; /* Read the Line Status Register (LSR) */ Lsr = HL::IoPort::ReadPort8(PtrToUshort(Port->Address + (ULONG)COMPORT_REG_LSR)); /* Check if expected byte is present */ if((Lsr & Byte) == 0) { /* Check Modem Status Register (MSR) for ring indicator */ Msr = HL::IoPort::ReadPort8(PtrToUshort(Port->Address + (ULONG)COMPORT_REG_MSR)); Port->Ring |= (Msr & COMPORT_MSR_RI) ? 1 : 2; if(Port->Ring == 3) { /* Ring indicator toggled, use modem control */ Port->Flags |= COMPORT_FLAG_MC; } } /* Return byte read */ return Lsr; } /** * This routine initializes the COM port. * * @param Port * Address of port object describing a port settings. * * @param PortNumber * Supplies a port number. * * @param PortAddress * Supplies an address of the COM port. * * @param BaudRate * Supplies an optional port baud rate. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTCDECL XTSTATUS HL::ComPort::InitializeComPort(IN OUT PCPPORT Port, IN PUCHAR PortAddress, IN ULONG BaudRate) { USHORT Flags; UCHAR Byte; ULONG Mode; /* Initialize variables */ Byte = 0; Flags = 0; /* Check if baud rate is set */ if(BaudRate == 0) { /* Use default baud (clock) rate if not set */ BaudRate = COMPORT_CLOCK_RATE; Flags |= COMPORT_FLAG_DBR; } /* Check whether this port is not already initialized */ if((Port->Address == PortAddress) && (Port->Baud == BaudRate)) { return STATUS_SUCCESS; } /* Test if chosen COM port exists */ do { /* Check whether the 16450/16550 scratch register exists */ HL::IoPort::WritePort8(PtrToUshort(PortAddress + (ULONG)COMPORT_REG_SR), Byte); if(HL::IoPort::ReadPort8(PtrToUshort(PortAddress + (ULONG)COMPORT_REG_SR)) != Byte) { return STATUS_NOT_FOUND; } } while(++Byte != 0); /* Disable interrupts */ HL::IoPort::WritePort8(PtrToUshort(PortAddress + (ULONG)COMPORT_REG_LCR), COMPORT_LSR_DIS); HL::IoPort::WritePort8(PtrToUshort(PortAddress + (ULONG)COMPORT_REG_IER), COMPORT_LSR_DIS); /* Enable Divisor Latch Access Bit (DLAB) */ HL::IoPort::WritePort8(PtrToUshort(PortAddress + (ULONG)COMPORT_REG_LCR), COMPORT_LCR_DLAB); /* Set baud rate */ Mode = COMPORT_CLOCK_RATE / BaudRate; HL::IoPort::WritePort8(PtrToUshort(PortAddress + (ULONG)COMPORT_DIV_DLL), (UCHAR)(Mode & 0xFF)); HL::IoPort::WritePort8(PtrToUshort(PortAddress + (ULONG)COMPORT_DIV_DLM), (UCHAR)((Mode >> 8) & 0xFF)); /* Set 8 data bits, 1 stop bits, no parity (8n1) */ HL::IoPort::WritePort8(PtrToUshort(PortAddress + (ULONG)COMPORT_REG_LCR), COMPORT_LCR_8DATA | COMPORT_LCR_1STOP | COMPORT_LCR_PARN); /* Enable DTR, RTS and OUT2 */ HL::IoPort::WritePort8(PtrToUshort(PortAddress + (ULONG)COMPORT_REG_MCR), COMPORT_MCR_DTR | COMPORT_MCR_RTS | COMPORT_MCR_OUT2); /* Enable FIFO */ HL::IoPort::WritePort8(PtrToUshort(PortAddress + (ULONG)COMPORT_REG_FCR), COMPORT_FCR_ENABLE | COMPORT_FCR_RCVR_RESET | COMPORT_FCR_TXMT_RESET); /* Mark port as fully initialized */ Flags |= COMPORT_FLAG_INIT; /* Make sure port works in Normal Operation Mode (NOM) */ HL::IoPort::WritePort8(PtrToUshort(PortAddress + (ULONG)COMPORT_REG_MCR), COMPORT_MCR_NOM); /* Read junk data out of the Receive Buffer Register (RBR) */ HL::IoPort::ReadPort8(PtrToUshort(PortAddress + (ULONG)COMPORT_REG_RBR)); /* Store port details */ Port->Address = PortAddress; Port->Baud = BaudRate; Port->Flags = Flags; Port->Ring = 0; /* Return success */ return STATUS_SUCCESS; } /** * This routine writes a byte to the serial port. * * @param Port * Address of port object describing a port settings. * * @param Byte * Data to be written. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTCDECL XTSTATUS HL::ComPort::WriteComPort(IN PCPPORT Port, IN UCHAR Byte) { UCHAR Lsr, Msr; /* Make sure the port has been initialized */ if(Port->Address == 0) { return STATUS_DEVICE_NOT_READY; } /* Check if port is in modem control */ while(Port->Flags & COMPORT_FLAG_MC) { /* Get the Modem Status Register (MSR) */ Msr = HL::IoPort::ReadPort8(PtrToUshort(Port->Address + (ULONG)COMPORT_REG_MSR)) & COMPORT_MSR_DSRCTSCD; if(Msr != COMPORT_MSR_DSRCTSCD) { /* Take character, if CD is not set */ Lsr = ReadComPortLsr(Port, 0); if((Msr & COMPORT_MSR_DCD) == 0 && (Lsr & COMPORT_LSR_DR) == COMPORT_LSR_DR) { /* Eat the character */ HL::IoPort::ReadPort8(PtrToUshort(Port->Address + (ULONG)COMPORT_REG_RBR)); } } else { /* CD, CTS and DSR are set, we can continue */ break; } } /* Wait for busy port */ while((ReadComPortLsr(Port, COMPORT_LSR_THRE) & COMPORT_LSR_THRE) == 0); /* Send byte to the port */ HL::IoPort::WritePort8(PtrToUshort(Port->Address + (ULONG)COMPORT_REG_THR), Byte); return STATUS_SUCCESS; } ================================================ FILE: xtoskrnl/hl/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/data.cc * DESCRIPTION: Hardware Layer global and static data * DEVELOPERS: Rafal Kupiec */ #include /* Tracks the total number of currently cached ACPI tables */ ULONG HL::Acpi::CacheCount = 0; /* Array holding the cached ACPI tables */ ACPI_CACHE_LIST HL::Acpi::CacheEntries[ACPI_MAX_CACHED_TABLES]; /* Head of the linked list tracking dynamically mapped ACPI tables */ LIST_ENTRY HL::Acpi::CacheList; /* Pointer to the ACPI Root System Description Pointer (RSDP) */ PACPI_RSDP HL::Acpi::RsdpStructure; /* Global architectural system states and hardware feature flags parsed from the ACPI tables */ ACPI_SYSTEM_INFO HL::Acpi::SystemInfo; /* Hardware configuration details and port addresses for the ACPI Power Management Timer */ ACPI_TIMER_INFO HL::Acpi::TimerInfo; /* Represents the number of active processors */ KAFFINITY HL::Cpu::ActiveProcessors; /* Metadata detailing the linear frame buffer geometry */ HL_FRAMEBUFFER_DATA HL::FrameBuffer::FrameBufferData; /* Pointer to the RAM shadow buffer used for double-buffered rendering */ PVOID HL::FrameBuffer::ScreenShadowBuffer; /* Tracks the bounding box, dimensions, and cursor position for the kernel video console */ HL_SCROLL_REGION_DATA HL::FrameBuffer::ScrollRegionData; /* Indicates the active hardware interrupt controller mode */ APIC_MODE HL::Pic::ApicMode; /* Total number of I/O APIC chips discovered and initialized */ ULONG HL::Pic::ControllerCount; /* Array containing MMIO bases, IDs, and line counts for all I/O APICs */ IOAPIC_DATA HL::Pic::Controllers[IOAPIC_MAX_CONTROLLERS]; /* Total number of legacy ISA interrupt routing overrides */ ULONG HL::Pic::IrqOverrideCount; /* Hardware routing definitions mapping legacy ISA interrupts to Global System Interrupts (GSI) */ ACPI_MADT_INTERRUPT_OVERRIDE HL::Pic::IrqOverrides[IOAPIC_MAX_OVERRIDES]; /* Lookup table mapping allocated hardware APIC vectors to their assigned Run Levels */ UCHAR HL::Pic::MappedVectors[256]; /* Accumulated tick value of the ACPI Power Management Timer */ ULONG HL::Timer::AcpiPmPerformanceCounter = 0; /* Primary hardware timer driving the periodic system clock interrupt */ TIMER_TYPE HL::Timer::ClockType; /* Fractional remainder used to maintain long-term system clock accuracy */ ULONG HL::Timer::FractionalIncrement = 0; /* Virtual address mapped to the HPET hardware MMIO registers */ PVOID HL::Timer::HpetAddress = NULLPTR; /* Operating frequency of the High Precision Event Timer in ticks per second */ ULONGLONG HL::Timer::HpetFrequency = 0; /* Spinlock protecting concurrent multiprocessor access to the global performance counters */ KSPIN_LOCK HL::Timer::PerformanceCounterLock; /* The performance counter frequency in ticks per second */ ULONGLONG HL::Timer::PerformanceFrequency = 0; /* Absolute monotonic tick count driven by the legacy Programmable Interval Timer */ ULONGLONG HL::Timer::PitPerformanceCounter; /* Programmed hardware divider interval used to increment the PIT performance counter */ ULONG HL::Timer::PitRollover; /* Flag indicating whether statistical system execution profiling is currently active */ BOOLEAN HL::Timer::ProfilingEnabled = FALSE; /* Tick interval required to trigger a profile interrupt */ ULONG HL::Timer::ProfilingTicks; /* Global accumulator for fractional time drift and precision compensation */ ULONG HL::Timer::RunningFraction = 0; /* System counter driven by the highest precision available hardware */ ULONGLONG HL::Timer::SystemPerformanceCounter; /* Current base clock increment in standard 100-nanosecond intervals */ ULONG HL::Timer::TimeIncrement = 0; /* Timer capabilities */ TIMER_CAPABILITIES HL::Timer::TimerCapabilities = {0}; /* APIC timer frequency */ ULONG HL::Timer::TimerFrequency; /* Function dispatch table for the active hardware timer backend */ TIMER_ROUTINES HL::Timer::TimerRoutines = {0}; /* Identifies the hardware timer backing */ TIMER_TYPE HL::Timer::TimerType; ================================================ FILE: xtoskrnl/hl/exports.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/exports.cc * DESCRIPTION: C-compatible API wrappers for exported kernel functions * DEVELOPERS: Aiken Harris */ #include /** * Retrieves the current value of the high-resolution performance counter. * * @param PerformanceFrequency * Suplies an optional pointer to a variable that receives the performance counter frequency in Hz. * * @return This routine returns the current 64-bit monotonic tick count. * * @since XT 1.0 */ XTCLINK XTAPI LARGE_INTEGER HlQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceFrequency) { return HL::Timer::QueryPerformanceCounter(PerformanceFrequency); } /** * Reads the 8-bit data from the specified I/O port. * * @param Port * Specifies the address to read from, in the range of 0-0xFFFF. * * @return The value read from the port. * * @since XT 1.0 */ XTCLINK XTCDECL UCHAR HlReadPort8(IN USHORT Port) { return HL::IoPort::ReadPort8(Port); } /** * Reads the 16-bit data from the specified I/O port. * * @param Port * Specifies the address to read from, in the range of 0-0xFFFF. * * @return The value read from the port. * * @since XT 1.0 */ XTCLINK XTCDECL USHORT HlReadPort16(IN USHORT Port) { return HL::IoPort::ReadPort16(Port); } /** * Reads the 32-bit data from the specified I/O port. * * @param Port * Specifies the address to read from, in the range of 0-0xFFFF. * * @return The value read from the port. * * @since XT 1.0 */ XTCLINK XTCDECL ULONG HlReadPort32(IN USHORT Port) { return HL::IoPort::ReadPort32(Port); } /** * Reads an 8-bit data from a specified register address. * * @param Register * Supplies a pointer to register address holding data to read. * * @return This routine returns a value at the specified register. * * @since XT 1.0 */ XTCLINK XTAPI UCHAR HlReadRegister8(IN PVOID Register) { return HL::IoRegister::ReadRegister8(Register); } /** * Reads a 16-bit data from a specified register address. * * @param Register * Supplies a pointer to register address holding data to read. * * @return This routine returns a value at the specified register. * * @since XT 1.0 */ XTCLINK XTAPI USHORT HlReadRegister16(IN PVOID Register) { return HL::IoRegister::ReadRegister16(Register); } /** * Reads a 32-bit data from a specified register address. * * @param Register * Supplies a pointer to register address holding data to read. * * @return This routine returns a value at the specified register. * * @since XT 1.0 */ XTCLINK XTAPI ULONG HlReadRegister32(IN PVOID Register) { return HL::IoRegister::ReadRegister32(Register); } /** * Requests a dynamic adjustment of the system clock resolution. * * @param Rate * The requested clock rate change in 100-nanosecond units. * * @return This routine returns the actual clock rate granted by the hardware. * * @since XT 1.0 */ XTCLINK XTAPI ULONG HlSetClockRate(IN ULONG Rate) { return HL::Timer::SetClockRate(Rate); } /** * Writes the 8-bit data to the specified I/O port. * * @param Port * Specifies the address to write to, in the range of 0-0xFFFF. * * @param Value * Supplies the value to write. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTCDECL VOID HlWritePort8(IN USHORT Port, IN UCHAR Value) { HL::IoPort::WritePort8(Port, Value); } /** * Writes the 16-bit data to the specified I/O port. * * @param Port * Specifies the address to write to, in the range of 0-0xFFFF. * * @param Value * Supplies the value to write. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTCDECL VOID HlWritePort16(IN USHORT Port, IN USHORT Value) { HL::IoPort::WritePort16(Port, Value); } /** * Writes the 32-bit data to the specified I/O port. * * @param Port * Specifies the address to write to, in the range of 0-0xFFFF. * * @param Value * Supplies the value to write. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTCDECL VOID HlWritePort32(IN USHORT Port, IN ULONG Value) { HL::IoPort::WritePort32(Port, Value); } /** * Writes an 8-bit value into a specified register address. * * @param Register * Supplies a pointer to register address where data will be written. * * @param Value * Supplies a new value that will be stored into a register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID HlWriteRegister8(IN PVOID Register, IN UCHAR Value) { HL::IoRegister::WriteRegister8(Register, Value); } /** * Writes a 16-bit value into a specified register address. * * @param Register * Supplies a pointer to register address where data will be written. * * @param Value * Supplies a new value that will be stored into a register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID HlWriteRegister16(IN PVOID Register, IN USHORT Value) { HL::IoRegister::WriteRegister16(Register, Value); } /** * Writes a 32-bit value into a specified register address. * * @param Register * Supplies a pointer to register address where data will be written. * * @param Value * Supplies a new value that will be stored into a register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID HlWriteRegister32(IN PVOID Register, IN ULONG Value) { HL::IoRegister::WriteRegister32(Register, Value); } ================================================ FILE: xtoskrnl/hl/fbdev.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/fbdev.cc * DESCRIPTION: FrameBuffer support * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include #include /** * Clears the screen by drawing a box filled with specified color. * * @param Color * Specifies the color of the box used to fill the screen in (A)RGB format. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::FrameBuffer::ClearScreen(IN ULONG Color) { ULONG BackgroundColor, PositionY; PCHAR CurrentLine, TargetBuffer; UCHAR FillByte; /* Make sure frame buffer is already initialized */ if(FrameBufferData.Initialized == FALSE) { /* Unable to operate on non-initialized frame buffer */ return; } /* Convert background color */ BackgroundColor = GetRGBColor(Color); /* Extract the lower byte for SetMemory */ FillByte = (UCHAR)(BackgroundColor & 0xFF); /* Determine target buffer */ TargetBuffer = (ScreenShadowBuffer != NULLPTR) ? (PCHAR)ScreenShadowBuffer : (PCHAR)FrameBufferData.Address; CurrentLine = TargetBuffer; /* Fill the screen with the specified color */ for(PositionY = 0; PositionY < FrameBufferData.Height; PositionY++, CurrentLine += FrameBufferData.Pitch) { /* Fill the current scanline with the background color byte */ RTL::Memory::SetMemory(CurrentLine, FillByte, FrameBufferData.Width * FrameBufferData.BytesPerPixel); } /* Check if Shadow Buffer is active */ if(ScreenShadowBuffer != NULLPTR) { /* Flush changes to VRAM */ RTL::Memory::CopyMemory(FrameBufferData.Address, ScreenShadowBuffer, FrameBufferData.Pitch * FrameBufferData.Height); } } /** * Displays a single character at the current cursor position inside the scroll region. * * @param Character * Supplies the character to be displayed. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL XTSTATUS HL::FrameBuffer::DisplayCharacter(IN WCHAR Character) { ULONG CharacterX, CharacterY; PSSFN_FONT_HEADER FbFont; BOOLEAN VisibleCharacter; /* Make sure frame buffer is already initialized */ if(FrameBufferData.Initialized == FALSE) { /* Unable to operate on non-initialized frame buffer */ return STATUS_DEVICE_NOT_READY; } /* Get font information */ FbFont = (PSSFN_FONT_HEADER)FrameBufferData.Font; /* Assume invisible character */ VisibleCharacter = FALSE; /* Handle special characters */ switch(Character) { case L'\n': /* Move cursor to the beginning of the next line */ ScrollRegionData.CursorX = ScrollRegionData.Left; ScrollRegionData.CursorY += FbFont->Height; break; case L'\t': /* Move cursor to the next tab stop */ ScrollRegionData.CursorX += (8 - (ScrollRegionData.CursorX - ScrollRegionData.Left) / FbFont->Width % 8) * FbFont->Width; if(ScrollRegionData.CursorX >= ScrollRegionData.Right) { ScrollRegionData.CursorX = ScrollRegionData.Left; ScrollRegionData.CursorY += FbFont->Height; } break; default: /* Save cursor position */ CharacterX = ScrollRegionData.CursorX; CharacterY = ScrollRegionData.CursorY; /* Draw the character to RAM and mark it as visible */ DrawCharacter(CharacterX, CharacterY, ScrollRegionData.TextColor, Character); VisibleCharacter = TRUE; /* Advance cursor */ ScrollRegionData.CursorX += FbFont->Width; /* Check if cursor reached end of line */ if(ScrollRegionData.CursorX >= ScrollRegionData.Right) { /* Reset cursor to the left margin and advance to the next line */ ScrollRegionData.CursorX = ScrollRegionData.Left; ScrollRegionData.CursorY += FbFont->Height; } break; } /* Check if cursor reached end of scroll region */ if(ScrollRegionData.CursorY >= ScrollRegionData.Bottom) { /* Scroll one line up */ ScrollRegion(); ScrollRegionData.CursorY = ScrollRegionData.Bottom - FbFont->Height; } else if(VisibleCharacter == TRUE) { /* Flush visible character to VRAM */ UpdateScreenRegion(CharacterX, CharacterY, CharacterX + FbFont->Width, CharacterY + FbFont->Height); } /* Return success */ return STATUS_SUCCESS; } /** * Draws a character on the framebuffer at the given position and color using the SSFN font. * * @param PositionX * Supplies the X coordinate of the character. * * @param PositionY * Supplies the Y coordinate of the character. * * @param Color * Supplies the font color in (A)RGB format. * * @param WideCharacter * Supplies the wide character to be drawn on the framebuffer. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::FrameBuffer::DrawCharacter(IN ULONG PositionX, IN ULONG PositionY, IN ULONG Color, IN WCHAR WideCharacter) { UINT CurrentFragment, Glyph, GlyphLimit, Index, Line, Mapping; PUCHAR Character, CharacterMapping, Fragment; ULONG FontColor, GlyphOffset, PixelOffset; PSSFN_FONT_HEADER FbFont; /* Make sure frame buffer is already initialized */ if(FrameBufferData.Initialized == FALSE) { /* Unable to operate on non-initialized frame buffer */ return; } /* Get pointers to font data */ FbFont = (PSSFN_FONT_HEADER)FrameBufferData.Font; CharacterMapping = (PUCHAR)FbFont + FbFont->CharactersOffset; /* Find the character in the font's character table */ Character = 0; for(Index = 0; Index < 0x110000; Index++) { if(CharacterMapping[0] == 0xFF) { /* Skip 65535 code points */ Index += 65535; CharacterMapping++; } else if((CharacterMapping[0] & 0xC0) == 0xC0) { /* Skip (N << 8 + additional byte) + 1 code points (up to 16128) */ Index += (((CharacterMapping[0] & 0x3F) << 8) | CharacterMapping[1]); CharacterMapping += 2; } else if((CharacterMapping[0] & 0xC0) == 0x80) { /* Skip N + 1 code points (up to 64) */ Index += (CharacterMapping[0] & 0x3F); CharacterMapping++; } else { /* There is a glyph for this character, check if it matches */ if(Index == WideCharacter) { /* Found the character, break loop */ Character = CharacterMapping; break; } /* Move to next character table entry */ CharacterMapping += (6 + CharacterMapping[1] * (CharacterMapping[0] & 0x40 ? 6 : 5)); } } /* Make sure the character has been found in the font */ if(!Character) { /* Character not found, don't draw anything */ return; } /* Find the glyph position on the frame buffer and set font color */ GlyphOffset = (PositionY * FrameBufferData.Pitch) + (PositionX * FrameBufferData.BytesPerPixel); FontColor = GetRGBColor(Color); /* Check all kerning fragments */ Mapping = 0; CharacterMapping = Character + 6; for(Index = 0; Index < Character[1]; Index++) { /* Check if number of fragments is not exceeded */ if(CharacterMapping[0] == 255 && CharacterMapping[1] == 255) { /* Get next mapping */ continue; } /* Get pointer to fragment */ Fragment = (PUCHAR)FbFont + (CharacterMapping[2] | (CharacterMapping[3] << 8) | (CharacterMapping[4] << 16) | ((Character[0] & 0x40) ? (CharacterMapping[5] << 24) : 0)); /* Check if fragment is printable */ if((Fragment[0] & 0xE0) != 0x80) { /* Skip fragment */ continue; } /* Get initial glyph line */ GlyphOffset += (CharacterMapping[1] - Mapping) * FrameBufferData.Pitch; Mapping = CharacterMapping[1]; /* Extract glyph data from fragments table and advance */ Glyph = ((Fragment[0] & 0x1F) + 1) << 3; GlyphLimit = Fragment[1] + 1; Fragment += 2; /* Look for kerning group for next code point */ CurrentFragment = 1; while(GlyphLimit--) { /* Set the initial pixel offset for the current glyph fragment */ PixelOffset = GlyphOffset; for(Line = 0; Line < Glyph; Line++) { /* Decode compressed offsets */ if(CurrentFragment > 0x80) { /* Advance to next fragment */ Fragment++; CurrentFragment = 1; } /* Check if pixel should be drawn */ if(*Fragment & CurrentFragment) { /* Route the pixel draw operation to the active buffer */ if(ScreenShadowBuffer != NULLPTR) { /* Draw glyph pixel to Shadow Buffer */ *((PULONG)((PCHAR)ScreenShadowBuffer + PixelOffset)) = FontColor; } else { /* Draw glyph pixel directly to VRAM */ *((PULONG)((PCHAR)FrameBufferData.Address + PixelOffset)) = FontColor; } } /* Advance pixel pointer */ PixelOffset += FrameBufferData.BytesPerPixel; CurrentFragment <<= 1; } /* Advance to next line and increase mapping */ GlyphOffset += FrameBufferData.Pitch; Mapping++; } /* Get next mapping */ CharacterMapping += Character[0] & 0x40 ? 6 : 5; } } /** * Draw a pixel on the screen at the given position and color. * * @param PositionX * Supplies the X coordinate of the pixel. * * @param PositionY * Supplies the Y coordinate of the pixel. * * @param Color * Specifies the color of the pixel in (A)RGB format. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::FrameBuffer::DrawPixel(IN ULONG PositionX, IN ULONG PositionY, IN ULONG Color) { ULONG Offset; /* Make sure frame buffer is already initialized */ if(FrameBufferData.Initialized == FALSE) { /* Unable to operate on non-initialized frame buffer */ return; } /* Make sure point is not offscreen */ if(PositionX >= FrameBufferData.Width || PositionY >= FrameBufferData.Height || Color > 0xFFFFFFFF) { /* Invalid pixel position or color given */ return; } /* Calculate the address of the pixel in the frame buffer memory */ Offset = (PositionY * FrameBufferData.Pitch) + (PositionX * FrameBufferData.BytesPerPixel); /* Route the pixel draw operation to the active buffer */ if(ScreenShadowBuffer != NULLPTR) { /* Set the color of the pixel by writing to the corresponding memory location (RAM) */ *((PULONG)((PCHAR)ScreenShadowBuffer + Offset)) = GetRGBColor(Color); } else { /* Set the color of the pixel by writing to the corresponding memory location (VRAM) */ *((PULONG)((PCHAR)FrameBufferData.Address + Offset)) = GetRGBColor(Color); } } /** * Enables the Shadow Buffer (Double Buffering) for high-performance rendering. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::FrameBuffer::EnableShadowBuffer(VOID) { ULONG FrameBufferSize; XTSTATUS Status; /* Check if the shadow buffer is already enabled */ if(ScreenShadowBuffer != NULLPTR) { /* Nothing to do, return success */ return STATUS_SUCCESS; } /* Make sure frame buffer is already initialized */ if(FrameBufferData.Initialized == FALSE) { /* Unable to operate on non-initialized frame buffer */ return STATUS_DEVICE_NOT_READY; } /* Calculate the total size of the framebuffer */ FrameBufferSize = FrameBufferData.Pitch * FrameBufferData.Height; /* Allocate non-paged memory for the shadow buffer */ Status = MM::Allocator::AllocatePool(NonPagedPool, FrameBufferSize, &ScreenShadowBuffer, SIGNATURE32('F', 'B', 'U', 'F')); if(Status != STATUS_SUCCESS) { /* Allocation failed, return status code */ ScreenShadowBuffer = NULLPTR; return Status; } /* Synchronize the newly allocated shadow buffer with the current on-screen contents */ RTL::Memory::CopyMemory(ScreenShadowBuffer, FrameBufferData.Address, FrameBufferSize); /* Return success */ return STATUS_SUCCESS; } /** * Returns the current resolution of the frame buffer display. * * @param Width * A pointer to memory area where the screen width will be stored. * * @param Height * A pointer to memory area where the screen height will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::FrameBuffer::GetFrameBufferResolution(OUT PULONG Width, OUT PULONG Height) { *Width = FrameBufferData.Width; *Height = FrameBufferData.Height; } /** * Converts color format from (A)RGB one expected by current FrameBuffer. * * @param Color * Specifies the color in (A)RGB format. * * @return This routine returns the color in FrameBuffer format. * * @since XT 1.0 */ XTAPI ULONG HL::FrameBuffer::GetRGBColor(IN ULONG Color) { USHORT Blue, Green, Red, Reserved; /* Extract color components from (A)RGB value */ Blue = (USHORT)(Color & 0xFF); Green = (USHORT)((Color >> 8) & 0xFF); Red = (USHORT)((Color >> 16) & 0xFF); Reserved = (USHORT)((Color >> 24) & 0xFF); /* Return color in FrameBuffer pixel format */ return (ULONG)((Blue << FrameBufferData.Pixels.BlueShift) | (Green << FrameBufferData.Pixels.GreenShift) | (Red << FrameBufferData.Pixels.RedShift) | (Reserved << FrameBufferData.Pixels.ReservedShift)); } /** * Initializes frame buffer display. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::FrameBuffer::InitializeFrameBuffer(VOID) { PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource; PSYSTEM_RESOURCE_HEADER SystemResource; XTSTATUS Status; /* Check if display already initialized */ if(FrameBufferData.Initialized) { /* Nothing to do */ return STATUS_SUCCESS; } /* Get FrameBuffer system resource */ Status = KeGetSystemResource(SystemResourceFrameBuffer, &SystemResource); if(Status != STATUS_SUCCESS) { /* Resource not found */ return STATUS_NOT_FOUND; } /* Cast system resource to FrameBuffer resource */ FrameBufferResource = (PSYSTEM_RESOURCE_FRAMEBUFFER)SystemResource; /* Check if bootloader provided a framebuffer address */ if(!FrameBufferResource->Header.VirtualAddress) { /* Display probably not initialized */ return STATUS_DEVICE_NOT_READY; } /* Check if bootloader provided a custom font */ if(FrameBufferResource->Font) { /* Use custom font */ FrameBufferData.Font = FrameBufferResource->Font; } else { /* Use default font */ FrameBufferData.Font = (PVOID)&XtFbDefaultFont; } /* Save framebuffer information and mark display as initialized */ FrameBufferData.Address = FrameBufferResource->Header.VirtualAddress; FrameBufferData.Width = FrameBufferResource->Width; FrameBufferData.Height = FrameBufferResource->Height; FrameBufferData.BytesPerPixel = FrameBufferResource->BitsPerPixel / 8; FrameBufferData.PixelsPerScanLine = FrameBufferResource->PixelsPerScanLine; FrameBufferData.Pitch = FrameBufferResource->Pitch; FrameBufferData.Pixels.BlueShift = FrameBufferResource->Pixels.BlueShift; FrameBufferData.Pixels.BlueSize = FrameBufferResource->Pixels.BlueSize; FrameBufferData.Pixels.GreenShift = FrameBufferResource->Pixels.GreenShift; FrameBufferData.Pixels.GreenSize = FrameBufferResource->Pixels.GreenSize; FrameBufferData.Pixels.RedShift = FrameBufferResource->Pixels.RedShift; FrameBufferData.Pixels.RedSize = FrameBufferResource->Pixels.RedSize; FrameBufferData.Pixels.ReservedShift = FrameBufferResource->Pixels.ReservedShift; FrameBufferData.Pixels.ReservedSize = FrameBufferResource->Pixels.ReservedSize; FrameBufferData.Initialized = TRUE; /* Clear screen */ ClearScreen(0x00000000); /* Return success */ return STATUS_SUCCESS; } /** * Sets the scrollable region of the screen and calculates character dimensions. * * @param Left * Supplies the left pixel coordinate of the scroll region. * * @param Top * Supplies the top pixel coordinate of the scroll region. * * @param Right * Supplies the right pixel coordinate of the scroll region. * * @param Bottom * Supplies the bottom pixel coordinate of the scroll region. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::FrameBuffer::InitializeScrollRegion(IN ULONG Left, IN ULONG Top, IN ULONG Right, IN ULONG Bottom, IN ULONG FontColor) { PSSFN_FONT_HEADER FbFont; PCHAR PixelAddress; /* Make sure frame buffer is already initialized */ if(FrameBufferData.Initialized == FALSE) { /* Unable to operate on non-initialized frame buffer */ return; } /* Store pixel coordinates of the scroll region */ ScrollRegionData.Left = Left; ScrollRegionData.Top = Top; ScrollRegionData.Right = Right; ScrollRegionData.Bottom = Bottom; /* Get font information */ FbFont = (PSSFN_FONT_HEADER)FrameBufferData.Font; /* Validate font information */ if(FbFont && FbFont->Width > 0 && FbFont->Height > 0) { /* Calculate character dimensions */ ScrollRegionData.WidthInChars = (Right - Left) / FbFont->Width; ScrollRegionData.HeightInChars = (Bottom - Top) / FbFont->Height; /* Ensure the bottom of the scroll region is an exact multiple of the font height */ ScrollRegionData.Bottom = ScrollRegionData.Top + (ScrollRegionData.HeightInChars * FbFont->Height); } else { /* Fallback to 0 if font info is not available or invalid */ ScrollRegionData.WidthInChars = 0; ScrollRegionData.HeightInChars = 0; } /* Initialize cursor position and font color */ ScrollRegionData.CursorX = ScrollRegionData.Left; ScrollRegionData.CursorY = ScrollRegionData.Top; ScrollRegionData.TextColor = FontColor; /* Get the background color by reading the pixel at the top-left corner of the scroll region */ PixelAddress = (PCHAR)FrameBufferData.Address + (Top * FrameBufferData.Pitch) + (Left * FrameBufferData.BytesPerPixel); ScrollRegionData.BackgroundColor = *((PULONG)PixelAddress); } /** * Scrolls the content of the scroll region up by one line. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::FrameBuffer::ScrollRegion(VOID) { PCHAR TargetBuffer, Destination, Source; ULONG Line, PositionX, LineBytes; PSSFN_FONT_HEADER FbFont; PULONG Pixel; /* Make sure frame buffer is already initialized */ if(FrameBufferData.Initialized == FALSE) { /* Unable to operate on non-initialized frame buffer */ return; } /* Retrieve font metrics and calculate line properties for the scroll operation */ FbFont = (PSSFN_FONT_HEADER)FrameBufferData.Font; LineBytes = (ScrollRegionData.Right - ScrollRegionData.Left) * FrameBufferData.BytesPerPixel; TargetBuffer = (ScreenShadowBuffer != NULLPTR) ? (PCHAR)ScreenShadowBuffer : (PCHAR)FrameBufferData.Address; /* Process every line in the scroll region */ for(Line = ScrollRegionData.Top; Line < ScrollRegionData.Bottom; Line++) { /* Calculate destination address for the current line */ Destination = TargetBuffer + (Line * FrameBufferData.Pitch) + (ScrollRegionData.Left * FrameBufferData.BytesPerPixel); /* Check if the current line needs to be copied from below or cleared */ if(Line < ScrollRegionData.Bottom - FbFont->Height) { /* Copy the line from below */ Source = Destination + (FbFont->Height * FrameBufferData.Pitch); RTL::Memory::CopyMemory(Destination, Source, LineBytes); } else { /* Fill the bottom line(s) with the background color */ Pixel = (PULONG)Destination; for(PositionX = 0; PositionX < (ScrollRegionData.Right - ScrollRegionData.Left); PositionX++) { /* Overwrite the pixel with the background color */ Pixel[PositionX] = ScrollRegionData.BackgroundColor; } } } /* Flush changes to VRAM if Shadow Buffer was used */ if(ScreenShadowBuffer != NULLPTR) { /* Flush the updated scroll region to VRAM */ UpdateScreenRegion(ScrollRegionData.Left, ScrollRegionData.Top, ScrollRegionData.Right, ScrollRegionData.Bottom); } } /** * Flushes the current content of the Shadow Buffer to the visible FrameBuffer (VRAM). * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::FrameBuffer::UpdateScreen(VOID) { /* Make sure framebuffer is already initialized and shadow buffer is ready */ if(FrameBufferData.Initialized == FALSE || ScreenShadowBuffer == NULLPTR) { /* Unable to operate on non-initialized frame buffer */ return; } /* Flush RAM to VRAM */ RTL::Memory::CopyMemory(FrameBufferData.Address, ScreenShadowBuffer, FrameBufferData.Pitch * FrameBufferData.Height); } /** * Flushes a specific rectangular region from the Shadow Buffer to the visible FrameBuffer (VRAM). * * @param Left * Supplies the left pixel coordinate of the region to update. * * @param Top * Supplies the top pixel coordinate of the region to update. * * @param Right * Supplies the right pixel coordinate of the region to update. * * @param Bottom * Supplies the bottom pixel coordinate of the region to update. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::FrameBuffer::UpdateScreenRegion(IN ULONG Left, IN ULONG Top, IN ULONG Right, IN ULONG Bottom) { ULONG Line, LineBytes; PCHAR Source, Destination; /* Make sure framebuffer is already initialized and shadow buffer is ready */ if(FrameBufferData.Initialized == FALSE || ScreenShadowBuffer == NULLPTR) { /* Unable to operate on non-initialized frame buffer */ return; } /* Make sure parameters are valid to prevent memory corruption */ if(Left >= Right || Top >= Bottom || Right > FrameBufferData.Width || Bottom > FrameBufferData.Height) { /* Invalid region coordinates provided */ return; } /* Calculate the width of the region */ LineBytes = (Right - Left) * FrameBufferData.BytesPerPixel; /* Copy the specified region line by line */ for(Line = Top; Line < Bottom; Line++) { /* Calculate the source address in the shadow buffer */ Source = (PCHAR)ScreenShadowBuffer + (Line * FrameBufferData.Pitch) + (Left * FrameBufferData.BytesPerPixel); /* Calculate the destination address in the VRAM */ Destination = (PCHAR)FrameBufferData.Address + (Line * FrameBufferData.Pitch) + (Left * FrameBufferData.BytesPerPixel); /* Flush RAM to VRAM */ RTL::Memory::CopyMemory(Destination, Source, LineBytes); } } ================================================ FILE: xtoskrnl/hl/i686/cpu.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/i686/cpu.cc * DESCRIPTION: HAL i686 processor support * DEVELOPERS: Rafal Kupiec */ #include /* Include common CPU interface */ #include ARCH_COMMON(cpu.cc) ================================================ FILE: xtoskrnl/hl/i686/firmware.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/i686/firmware.cc * DESCRIPTION: UEFI/BIOS Firmware support * DEVELOPERS: Aiken Harris */ #include /* Include common Firmware interface */ #include ARCH_COMMON(firmware.cc) ================================================ FILE: xtoskrnl/hl/i686/ioport.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/i686/ioport.cc * DESCRIPTION: I/O port access routines for i686 platform * DEVELOPERS: Rafal Kupiec */ #include /** * Reads the 8-bit data from the specified I/O port. * * @param Port * Specifies the address to read from, in the range of 0-0xFFFF. * * @return This routine returns the value read from the port. * * @since XT 1.0 */ XTCDECL UCHAR HL::IoPort::ReadPort8(IN USHORT Port) { UCHAR Value; __asm__ volatile("inb %1, %0" : "=a" (Value) : "Nd" (Port)); return Value; } /** * Reads the 16-bit data from the specified I/O port. * * @param Port * Specifies the address to read from, in the range of 0-0xFFFF. * * @return This routine returns the value read from the port. * * @since XT 1.0 */ XTCDECL USHORT HL::IoPort::ReadPort16(IN USHORT Port) { USHORT Value; __asm__ volatile("inw %1, %0" : "=a" (Value) : "Nd" (Port)); return Value; } /** * Reads the 32-bit data from the specified I/O port. * * @param Port * Specifies the address to read from, in the range of 0-0xFFFF. * * @return This routine returns the value read from the port. * * @since XT 1.0 */ XTCDECL ULONG HL::IoPort::ReadPort32(IN USHORT Port) { ULONG Value; __asm__ volatile("inl %1, %0" : "=a" (Value) : "Nd" (Port)); return Value; } /** * Writes the 8-bit data to the specified I/O port. * * @param Port * Specifies the address to write to, in the range of 0-0xFFFF. * * @param Value * Supplies the value to write. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HL::IoPort::WritePort8(IN USHORT Port, IN UCHAR Value) { __asm__ volatile("outb %0, %1" : : "a" (Value), "Nd" (Port)); } /** * Writes the 16-bit data to the specified I/O port. * * @param Port * Specifies the address to write to, in the range of 0-0xFFFF. * * @param Value * Supplies the value to write. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HL::IoPort::WritePort16(IN USHORT Port, IN USHORT Value) { __asm__ volatile("outw %0, %1" : : "a" (Value), "Nd" (Port)); } /** * Writes the 32-bit data to the specified I/O port. * * @param Port * Specifies the address to write to, in the range of 0-0xFFFF. * * @param Value * Supplies the value to write. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HL::IoPort::WritePort32(IN USHORT Port, IN ULONG Value) { __asm__ volatile("outl %0, %1" : : "a" (Value), "Nd" (Port)); } ================================================ FILE: xtoskrnl/hl/i686/irq.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/i686/irq.cc * DESCRIPTION: Interrupts support for i686 architecture * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Begins a system interrupt handler by raising the processor's run level and re-enabling * hardware interrupts to allow preemption by higher-priority events. * * @param RunLevel * Supplies the target run level to raise the processor to. * * @param OldRunLevel * Receives the previous run level before the elevation. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Irq::BeginSystemInterrupt(IN KRUNLEVEL RunLevel, OUT PKRUNLEVEL OldRunLevel) { /* Get the current IRQL */ *OldRunLevel = KE::RunLevel::GetCurrentRunLevel(); /* Raise run level */ KE::RunLevel::RaiseRunLevel(RunLevel); /* Enable interrupts */ AR::CpuFunctions::SetInterruptFlag(); } /** * Safely concludes an interrupt handler by disabling hardware interrupts. * * @param TrapFrame * Supplies a pointer to the kernel trap frame containing the interrupted execution state. * * @param OldRunLevel * Supplies the previous run level to restore. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Irq::EndInterrupt(IN PKTRAP_FRAME TrapFrame, IN KRUNLEVEL OldRunLevel) { /* Disable interrupts */ AR::CpuFunctions::ClearInterruptFlag(); /* End system interrupt */ EndSystemInterrupt(TrapFrame, OldRunLevel); } /** * Concludes a system interrupt by sending an End of Interrupt (EOI) to the hardware * controller and restoring the processor's previous run level. * * @param TrapFrame * Supplies a pointer to the kernel trap frame containing the interrupted execution state. * * @param OldRunLevel * Supplies the previous run level to restore. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Irq::EndSystemInterrupt(IN PKTRAP_FRAME TrapFrame, IN KRUNLEVEL OldRunLevel) { /* Send EOI */ HL::Pic::SendEoi(); /* Restore previous run level */ KE::RunLevel::LowerRunLevel(OldRunLevel); } /** * Handles profiling interrupt. * * @param TrapFrame * Supplies a kernel trap frame pushed by common interrupt handler. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HL::Irq::HandleProfileInterrupt(IN PKTRAP_FRAME TrapFrame) { /* Send EOI */ HL::Pic::SendEoi(); } /** * Handles unexpected or unmapped system interrupts. * * @param TrapFrame * Supplies a kernel trap frame pushed by common interrupt handler. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HL::Irq::HandleUnexpectedInterrupt(IN PKTRAP_FRAME TrapFrame) { UNIMPLEMENTED; /* Disable interrupts */ AR::CpuFunctions::ClearInterruptFlag(); /* Print debug message and raise kernel panic */ DebugPrint(L"ERROR: Caught unexpected interrupt (0x%.2lX)!\n", TrapFrame->Vector); KE::Crash::Panic(0x47, TrapFrame->Vector, 0, 0, 0); } /** * Returns the registered interrupt handler for the specified IDT vector. * * @param Vector * Supplies the interrupt vector number. * * @return This routine returns the pointer to the IDT interrupt handler routine. * * @since XT 1.0 */ XTAPI PVOID HL::Irq::QueryInterruptHandler(IN ULONG Vector) { PKPROCESSOR_BLOCK ProcessorBlock; PKIDTENTRY IdtEntry; /* Get current processor block and IDT entry */ ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); IdtEntry = &ProcessorBlock->IdtBase[Vector]; /* Return address of the interrupt handler */ return (PVOID)(((IdtEntry->ExtendedOffset << 16) & 0xFFFF0000) | (IdtEntry->Offset & 0xFFFF)); } /** * Returns the registered interrupt handler for the specified vector. * * @param Vector * Supplies the interrupt vector number. * * @return This routine returns the pointer to the interrupt handler routine. * * @since XT 1.0 */ XTAPI PVOID HL::Irq::QuerySystemInterruptHandler(IN ULONG Vector) { PKPROCESSOR_BLOCK ProcessorBlock; /* Get current processor block */ ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); return (PVOID)ProcessorBlock->InterruptDispatchTable[Vector]; } /** * Registers new interrupt handler for the existing IDT entry. * * @param HalVector * Supplies the interrupt vector number. * * @param Handler * Supplies the pointer to the interrupt handler routine. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Irq::RegisterInterruptHandler(IN ULONG Vector, IN PVOID Handler) { PKPROCESSOR_BLOCK ProcessorBlock; /* Get current processor block */ ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); /* Update interrupt handler */ AR::ProcessorSupport::SetIdtGate(ProcessorBlock->IdtBase, Vector, Handler, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); } /** * Registers the interrupt handler for the specified vector. * * @param HalVector * Supplies the interrupt vector number. * * @param Handler * Supplies the pointer to the interrupt handler routine. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Irq::RegisterSystemInterruptHandler(IN ULONG Vector, IN PINTERRUPT_HANDLER Handler) { PKPROCESSOR_BLOCK ProcessorBlock; /* Get current processor block */ ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); /* Update interrupt handler in the processor's interrupt dispatch table */ ProcessorBlock->InterruptDispatchTable[Vector] = Handler; } /** * Requests a software interrupt by sending a Self-IPI mapped to the specified run level. * * @param RunLevel * Supplies the target run level for the software interrupt. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID HL::Irq::SendSoftwareInterrupt(IN KRUNLEVEL RunLevel) { /* Request a software interrupt */ HL::Pic::SendSelfIpi(HL::RunLevel::TransformRunLevelToSoftwareVector(RunLevel)); } ================================================ FILE: xtoskrnl/hl/i686/pic.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/i686/pic.cc * DESCRIPTION: Programmable Interrupt Controller (PIC) for i686 support * DEVELOPERS: Rafal Kupiec */ #include /* Include common PIC interface */ #include ARCH_COMMON(pic.cc) ================================================ FILE: xtoskrnl/hl/i686/rtc.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/i686/rtc.cc * DESCRIPTION: Hardware Real-Time Clock (RTC) support * DEVELOPERS: Aiken Harris */ #include /* Include common RTC interface */ #include ARCH_COMMON(rtc.cc) ================================================ FILE: xtoskrnl/hl/i686/runlevel.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/i686/runlevel.cc * DESCRIPTION: Run Level management support for i686 architecture * DEVELOPERS: Rafal Kupiec */ #include /** * Gets the current run level from APIC for the current processor. * * @return This routine returns the current run level. * * @since XT 1.0 */ XTFASTCALL KRUNLEVEL HL::RunLevel::GetRunLevel(VOID) { /* Read current run level */ return TransformApicTprToRunLevel(HL::Pic::ReadApicRegister(APIC_TPR)); } /** * Sets new run level for the current processor. * * @param RunLevel * Supplies the new run level to store into APIC. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID HL::RunLevel::SetRunLevel(IN KRUNLEVEL RunLevel) { /* Set new run level */ HL::Pic::WriteApicRegister(APIC_TPR, TransformRunLevelToApicTpr(RunLevel)); } /** * Maps APIC interrupt vector to XT run level. * * @param Tpr * Supplies the interrupt vector rad from APIC Task Priority Register. * * @return This routine returns the XT run level corresponding to the specified APIC interrupt vector. * * @since XT 1.0 */ XTFASTCALL KRUNLEVEL HL::RunLevel::TransformApicTprToRunLevel(IN UCHAR Tpr) { STATIC KRUNLEVEL TransformationTable[16] = { PASSIVE_LEVEL, PASSIVE_LEVEL, PASSIVE_LEVEL, APC_LEVEL, DISPATCH_LEVEL, DEVICE1_LEVEL, DEVICE2_LEVEL, DEVICE3_LEVEL, DEVICE4_LEVEL, DEVICE5_LEVEL, DEVICE6_LEVEL, DEVICE7_LEVEL, PROFILE_LEVEL, CLOCK_LEVEL, IPI_LEVEL, HIGH_LEVEL }; /* Return the run level corresponding to the TPR from the transformation table. */ return TransformationTable[Tpr / 16]; } /** * Maps XT run level to interrupt vector suitable for the APIC Task Priority Register. * * @param RunLevel * Supplies the XT run level. * * @return This routine returns the APIC interrupt vector corresponding to the specified XT run level. * * @since XT 1.0 */ XTFASTCALL UCHAR HL::RunLevel::TransformRunLevelToApicTpr(IN KRUNLEVEL RunLevel) { STATIC UCHAR TransformationTable[32] = { APIC_VECTOR_ZERO, APIC_VECTOR_APC, APIC_VECTOR_DPC, APIC_VECTOR_DPC, APIC_VECTOR_DEVICE1, APIC_VECTOR_DEVICE2, APIC_VECTOR_DEVICE3, APIC_VECTOR_DEVICE4, APIC_VECTOR_DEVICE5, APIC_VECTOR_DEVICE6, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_DEVICE7, APIC_VECTOR_GENERIC, APIC_VECTOR_CLOCK, APIC_VECTOR_IPI, APIC_VECTOR_POWERFAIL, APIC_VECTOR_NMI }; /* Return the TPR corresponding to the run level from the transformation table. */ return TransformationTable[RunLevel]; } /** * Transforms a given execution run level into a corresponding hardware interrupt vector * suitable for software interrupts. * * @param RunLevel * Supplies the run level to be translated into a software interrupt vector. * * @return This routine returns the 8-bit APIC vector corresponding to the requested software interrupt level. * * @since XT 1.0 */ XTFASTCALL UCHAR HL::RunLevel::TransformRunLevelToSoftwareVector(IN KRUNLEVEL RunLevel) { /* Transform run level to APIC interrupt vector */ return TransformRunLevelToApicTpr(RunLevel); } ================================================ FILE: xtoskrnl/hl/i686/timer.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/i686/timer.cc * DESCRIPTION: Timer support for i686 * DEVELOPERS: Aiken Harris */ #include /* Include common Timer interface */ #include ARCH_COMMON(timer.cc) ================================================ FILE: xtoskrnl/hl/init.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/init.cc * DESCRIPTION: Hardware layer initialization code * DEVELOPERS: Rafal Kupiec */ #include /** * Initializes the hardware layer subsystem * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Init::InitializeSystem(VOID) { XTSTATUS Status; /* Initialize ACPI */ Status = HL::Acpi::InitializeAcpi(); if(Status != STATUS_SUCCESS) { return Status; } /* Get system information from ACPI */ Status = HL::Acpi::InitializeAcpiSystemInformation(); if(Status != STATUS_SUCCESS) { return Status; } /* Initialize I/O APIC */ HL::Pic::InitializeIOApic(); /* Initialize timer */ HL::Timer::InitializeTimer(); /* Return success */ return STATUS_SUCCESS; } ================================================ FILE: xtoskrnl/hl/ioreg.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/ioreg.cc * DESCRIPTION: Basic I/O registers access functionality * DEVELOPERS: Rafal Kupiec */ #include /** * Reads an 8-bit data from a specified register address. * * @param Register * Supplies a pointer to register address holding data to read. * * @return This routine returns a value at the specified register. * * @since XT 1.0 */ XTAPI UCHAR HL::IoRegister::ReadRegister8(IN PVOID Register) { return *((VOLATILE PUCHAR)Register); } /** * Reads a 16-bit data from a specified register address. * * @param Register * Supplies a pointer to register address holding data to read. * * @return This routine returns a value at the specified register. * * @since XT 1.0 */ XTAPI USHORT HL::IoRegister::ReadRegister16(IN PVOID Register) { return *((VOLATILE PUSHORT)Register); } /** * Reads a 32-bit data from a specified register address. * * @param Register * Supplies a pointer to register address holding data to read. * * @return This routine returns a value at the specified register. * * @since XT 1.0 */ XTAPI ULONG HL::IoRegister::ReadRegister32(IN PVOID Register) { return *((VOLATILE PULONG)Register); } /** * Writes an 8-bit value into a specified register address. * * @param Register * Supplies a pointer to register address where data will be written. * * @param Value * Supplies a new value that will be stored into a register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::IoRegister::WriteRegister8(IN PVOID Register, IN UCHAR Value) { *((VOLATILE PUCHAR)Register) = Value; } /** * Writes a 16-bit value into a specified register address. * * @param Register * Supplies a pointer to register address where data will be written. * * @param Value * Supplies a new value that will be stored into a register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::IoRegister::WriteRegister16(IN PVOID Register, IN USHORT Value) { *((VOLATILE PUSHORT)Register) = Value; } /** * Writes a 32-bit value into a specified register address. * * @param Register * Supplies a pointer to register address where data will be written. * * @param Value * Supplies a new value that will be stored into a register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::IoRegister::WriteRegister32(IN PVOID Register, IN ULONG Value) { *((VOLATILE PULONG)Register) = Value; } ================================================ FILE: xtoskrnl/hl/x86/cpu.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/x86/cpu.cc * DESCRIPTION: HAL x86 (i686/AMD64) processor support * DEVELOPERS: Rafal Kupiec */ #include /** * Initializes the processor. * * @param CpuNumber * Supplies the number of the CPU, that is being initialized. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Cpu::InitializeProcessor(VOID) { PKPROCESSOR_BLOCK ProcessorBlock; KAFFINITY Affinity; /* Get current processor block */ ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); /* Set initial stall factor, CPU number and mask interrupts */ ProcessorBlock->StallScaleFactor = INITIAL_STALL_FACTOR; ProcessorBlock->Idr = 0xFFFFFFFF; /* Set processor affinity */ Affinity = (KAFFINITY) 1 << ProcessorBlock->CpuNumber; /* Apply affinity to a set of processors */ ActiveProcessors |= Affinity; /* Initialize APIC for this processor */ HL::Pic::InitializePic(); /* Set the APIC running level */ HL::RunLevel::SetRunLevel(KE::Processor::GetCurrentProcessorBlock()->RunLevel); } /** * Wakes up and initializes all Application Processors (APs) and transitions them into the active kernel. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Cpu::StartAllProcessors(VOID) { ULONG CpuNumber, Index, MaxCpus, SipiVector, Timeout, TrampolinePages; PVOID CpuStructures, TrampolineAddress, TrampolineCode; ULONG_PTR AllocationSize, TrampolineCodeSize; PPROCESSOR_START_BLOCK StartBlock; PKPROCESSOR_BLOCK ProcessorBlock; PACPI_SYSTEM_INFO SysInfo; WCHAR ParameterValue[16]; XTSTATUS Status; /* Determine the maximum number of CPUs to start */ HL::Acpi::GetSystemInformation(&SysInfo); MaxCpus = SysInfo->CpuCount; /* Check if user forced a specific CPU limit */ if(KE::BootInformation::GetKernelParameterValue(L"MAXCPUS", ParameterValue, 16) == STATUS_SUCCESS) { /* Convert string value to number */ Status = RTL::WideString::WideStringToNumber(ParameterValue, 0, &MaxCpus); if(Status == STATUS_SUCCESS) { /* Ensure safe boundaries */ if(MaxCpus == 0) { /* Fallback to 1 CPU (BSP) */ MaxCpus = 1; } } else { /* Failed to parse value, fallback to ACPI value */ MaxCpus = SysInfo->CpuCount; } } /* Check if single core CPU or set a CPU limit */ if(MaxCpus == 1 || SysInfo->CpuCount == 1) { /* Single core CPU, return success */ return STATUS_SUCCESS; } /* Get trampoline information */ AR::ProcessorSupport::GetTrampolineInformation(TrampolineApStartup, &TrampolineCode, &TrampolineCodeSize); /* Verify trampoline information */ if(TrampolineCode == NULLPTR || TrampolineCodeSize == 0) { /* Failed to get trampoline information, return error */ return STATUS_UNSUCCESSFUL; } /* Compute trampoline memory allocation size (trampoline + processor start block + temporary stack) */ AllocationSize = TrampolineCodeSize + sizeof(PROCESSOR_START_BLOCK) + 512; TrampolinePages = (ULONG)(ROUND_UP(AllocationSize, MM_PAGE_SIZE) / MM_PAGE_SIZE); /* Allocate real mode memory for AP trampoline */ Status = MM::HardwarePool::AllocateRealModeMemory(TrampolinePages, &TrampolineAddress); if(Status != STATUS_SUCCESS) { /* Failed to allocate memory, print error message and return error */ DebugPrint(L"Failed to allocate %lu pages for AP Trampoline!\n", TrampolinePages); return Status; } /* Copy trampoline code to low memory */ RTL::Memory::CopyMemory(TrampolineAddress, TrampolineCode, TrampolineCodeSize); /* Get start block address relative to trampoline address */ StartBlock = (PPROCESSOR_START_BLOCK)((PUCHAR)TrampolineAddress + TrampolineCodeSize); /* Get SIPI vector */ SipiVector = (ULONG)((ULONG_PTR)TrampolineAddress >> 12); /* Loop over all CPUs */ CpuNumber = 0; for(Index = 0; Index < SysInfo->CpuCount; Index++) { /* Check if destination CPU is the BSP */ if(SysInfo->CpuInfo[Index].ApicId == HL::Pic::GetCpuApicId()) { /* Skip current CPU */ continue; } /* Increment CPU number */ CpuNumber++; /* Verify if the CPU limit has been reached */ if((CpuNumber) >= MaxCpus) { /* Maximum allowed CPUs reached, break the loop */ break; } /* Allocate memory for the processor structures (Stacks, GDT, and Processor Block) */ Status = MM::KernelPool::AllocateProcessorStructures(&CpuStructures); if(Status != STATUS_SUCCESS) { /* Failed to allocate memory, unmap memory and return error */ MM::HardwarePool::UnmapHardwareMemory(TrampolineAddress, TrampolinePages, TRUE); return Status; } /* Get ProcessorBlock and Stack address */ AR::ProcessorSupport::InitializeProcessorStructures(CpuStructures, NULLPTR, NULLPTR, &ProcessorBlock, &StartBlock->Stack, NULLPTR, NULLPTR); /* Set processor number directly in the processor block */ ProcessorBlock->CpuNumber = CpuNumber; /* Save processor block in the array */ KE::Processor::RegisterProcessorBlock(CpuNumber, ProcessorBlock); /* Initialize processor start block */ StartBlock->Cr3 = AR::CpuFunctions::ReadControlRegister(3); StartBlock->Cr4 = AR::CpuFunctions::ReadControlRegister(4); StartBlock->EntryPoint = (PVOID)&KE::KernelInit::BootstrapApplicationProcessor; StartBlock->ProcessorStructures = CpuStructures; StartBlock->Started = FALSE; /* Memory barrier */ AR::CpuFunctions::MemoryBarrier(); /* Send INIT IPI and wait for 10ms */ HL::Pic::SendIpi(SysInfo->CpuInfo[Index].ApicId, 0, APIC_DM_INIT, APIC_DSH_Destination, APIC_TGM_EDGE); HL::Timer::StallExecution(10000); /* Send STARTUP IPI (SIPI) and wait for 200us */ HL::Pic::SendIpi(SysInfo->CpuInfo[Index].ApicId, SipiVector, APIC_DM_STARTUP, APIC_DSH_Destination, APIC_TGM_EDGE); HL::Timer::StallExecution(200); /* Send STARTUP IPI (SIPI) again */ HL::Pic::SendIpi(SysInfo->CpuInfo[Index].ApicId, SipiVector, APIC_DM_STARTUP, APIC_DSH_Destination, APIC_TGM_EDGE); /* Wait until the processor has started or timeout expires */ Timeout = 0; while(!StartBlock->Started && Timeout < 100000) { /* Yield processor and wait for 10us */ AR::CpuFunctions::YieldProcessor(); HL::Timer::StallExecution(10); Timeout++; } /* Check if the processor has not started */ if(!StartBlock->Started) { /* Free processor structures and unregister processor block */ MM::KernelPool::FreeProcessorStructures(CpuStructures); KE::Processor::RegisterProcessorBlock(CpuNumber, NULLPTR); /* Decrement the CPU counter back */ CpuNumber--; } } /* Unmap trampoline memory and return success */ MM::HardwarePool::UnmapHardwareMemory(TrampolineAddress, TrampolinePages, TRUE); return STATUS_SUCCESS; } ================================================ FILE: xtoskrnl/hl/x86/firmware.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/x86/firmware.cc * DESCRIPTION: UEFI/BIOS Firmware support * DEVELOPERS: Aiken Harris */ #include /** * Reads a byte from the specified CMOS register. * * @param Register * Supplies the CMOS register index to read from. * * @return This routine returns the data read from the register. * * @since XT 1.0 */ XTFASTCALL UCHAR HL::Firmware::ReadCmosRegister(IN UCHAR Register) { /* Select the register (Setting the highest bit disables NMI) */ HL::IoPort::WritePort8(CMOS_SELECT_PORT, Register | CMOS_NMI_SELECT); /* Read value from the data port */ return HL::IoPort::ReadPort8(CMOS_DATA_PORT); } /** * Writes a byte to the specified CMOS register. * * @param Register * Supplies the CMOS register index to write to. * * @param Value * Supplies the value to write to the register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID HL::Firmware::WriteCmosRegister(IN UCHAR Register, IN UCHAR Value) { /* Select the register (Setting the highest bit disables NMI) */ HL::IoPort::WritePort8(CMOS_SELECT_PORT, Register | CMOS_NMI_SELECT); /* Write the provided value to the data port */ HL::IoPort::WritePort8(CMOS_DATA_PORT, Value); } ================================================ FILE: xtoskrnl/hl/x86/pic.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/x86/pic.cc * DESCRIPTION: Programmable Interrupt Controller (PIC) for x86 (i686/AMD64) support * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Allocates, maps and commits a requested system interrupt level internally. * * @param Irq * Supplies the hardware IRQ line number to be allocated and mapped. * * @param RunLevel * Supplies the actual system run level to allocate. * * @param Vector * Supplies the interrupt handler vector assigned to process requests originating on the line. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Pic::AllocateSystemInterrupt(IN UCHAR Irq, IN UCHAR RunLevel, IN UCHAR Vector) { IOAPIC_REDIRECTION_REGISTER Register; PIOAPIC_DATA Controller; ULONG EntryNumber, Gsi; XTSTATUS Status; USHORT Flags; /* Determine the GSI and flags for the requested IRQ */ ResolveInterruptOverride(Irq, &Gsi, &Flags); /* Find the APIC controller for the GSI */ Status = GetIoApicController(Gsi, &Controller, &EntryNumber); if(Status != STATUS_SUCCESS) { /* GSI maps to an invalid controller, return */ DebugPrint(L"ERROR: Hardware IRQ / GSI maps to an invalid controller!\n"); return; } /* Model a logical connection */ Register.LongLong = 0; Register.DeliveryMode = APIC_DM_FIXED; Register.DeliveryStatus = 0; Register.Destination = HL::Pic::ReadApicRegister(APIC_ID) >> 24; Register.DestinationMode = APIC_DM_Physical; Register.Mask = 0; Register.PinPolarity = ((Flags & 0x03) == 0x03) ? 1 : 0; Register.RemoteIRR = 0; Register.Reserved = 0; Register.TriggerMode = (((Flags >> 2) & 0x03) == 0x03) ? APIC_TGM_LEVEL : APIC_TGM_EDGE; Register.Vector = Vector; /* Flash logical rules back into the hardware configuration index */ WriteRedirectionEntry(Controller, EntryNumber, Register); /* Persist the allocated slot so standard routing algorithms don't overlap it */ MappedVectors[Vector] = RunLevel; } /** * Checks whether the APIC is supported by the processor. * * @return This routine returns TRUE if APIC is supported, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN HL::Pic::CheckApicSupport(VOID) { PKPROCESSOR_CONTROL_BLOCK Prcb; /* Get current processor control block */ Prcb = KE::Processor::GetCurrentProcessorControlBlock(); /* Return APIC status */ return (Prcb->CpuId.FeatureBits & KCF_APIC) ? TRUE : FALSE; } /** * Checks whether the x2APIC extension is supported by the processor. * * @return This routine returns TRUE if x2APIC is supported, or FALSE otherwise. * * @since XT 1.0 * * @todo Check if bits 0 and 1 of DMAR ACPI table flags are set after implementing ACPI support. * Intel VT-d spec says x2apic should not be enabled if they are. */ XTAPI BOOLEAN HL::Pic::CheckX2ApicSupport(VOID) { PKPROCESSOR_CONTROL_BLOCK Prcb; PCWSTR KernelParameter; /* Check if the user forced xAPIC via boot parameters */ if(KE::BootInformation::GetKernelParameter(L"NOX2APIC", &KernelParameter) == STATUS_SUCCESS) { /* The NOX2APIC flag is present, explicitly disable x2APIC support */ return FALSE; } /* Get current processor control block */ Prcb = KE::Processor::GetCurrentProcessorControlBlock(); /* Return x2APIC status */ return (Prcb->CpuId.FeatureBits & KCF_X2APIC) ? TRUE : FALSE; } /** * Clears all errors on the APIC. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Pic::ClearApicErrors(VOID) { /* Clear APIC errors */ WriteApicRegister(APIC_ESR, 0); } /** * Searches the ACPI MADT tables for the I/O APIC controllers. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Pic::DetectIoApicControllers(VOID) { PACPI_MADT_INTERRUPT_OVERRIDE OverrideDescriptor; PACPI_MADT_IOAPIC IoApicDescriptor; PACPI_SUBTABLE_HEADER SubTable; ULONG_PTR MadtTable; PACPI_MADT Madt; XTSTATUS Status; /* Initialize number of I/O APIC Controllers */ ControllerCount = 0; /* Get Multiple APIC Description Table (MADT) */ Status = HL::Acpi::GetAcpiTable(ACPI_MADT_SIGNATURE, (PACPI_DESCRIPTION_HEADER*)&Madt); if(Status == STATUS_SUCCESS && Madt != NULLPTR) { /* Set APIC table traverse pointer */ MadtTable = (ULONG_PTR)Madt->ApicTables; /* Traverse all MADT tables to discover IOAPIC configurations */ while(MadtTable < ((ULONG_PTR)Madt + Madt->Header.Length)) { /* Extract active header element */ SubTable = (PACPI_SUBTABLE_HEADER)MadtTable; /* Prevent infinite traversal loops on corrupted firmware definitions */ if(SubTable->Length == 0) { /* Invalid MADT table, break loop */ break; } /* Test specifically for I/O APIC component identity */ if(SubTable->Type == ACPI_MADT_TYPE_IOAPIC && SubTable->Length >= sizeof(ACPI_MADT_IOAPIC)) { /* Extract I/O APIC descriptor */ IoApicDescriptor = (PACPI_MADT_IOAPIC)MadtTable; /* Set information about this I/O APIC Controller */ Controllers[ControllerCount].GsiBase = IoApicDescriptor->GlobalIrqBase; Controllers[ControllerCount].Identifier = IoApicDescriptor->IoApicId; Controllers[ControllerCount].PhysicalAddress.QuadPart = IoApicDescriptor->IoApicAddress; /* Increment I/O APIC controller index */ ControllerCount++; } else if(SubTable->Type == ACPI_MADT_TYPE_INT_OVERRIDE && SubTable->Length >= sizeof(ACPI_MADT_INTERRUPT_OVERRIDE)) { /* Check if maximum number of interrupt overrides has not been reached */ if(IrqOverrideCount < IOAPIC_MAX_OVERRIDES) { /* Extract interrupt override descriptor */ OverrideDescriptor = (PACPI_MADT_INTERRUPT_OVERRIDE)MadtTable; /* Save information about this interrupt override */ IrqOverrides[IrqOverrideCount].Bus = OverrideDescriptor->Bus; IrqOverrides[IrqOverrideCount].Flags = OverrideDescriptor->Flags; IrqOverrides[IrqOverrideCount].GlobalSystemInterrupt = OverrideDescriptor->GlobalSystemInterrupt; IrqOverrides[IrqOverrideCount].SourceIrq = OverrideDescriptor->SourceIrq; /* Increment interrupt override index */ IrqOverrideCount++; } } /* Ensure, maximum number of I/O APIC controllers has not been reached */ if(ControllerCount >= IOAPIC_MAX_CONTROLLERS) { /* No more I/O APIC controllers supported, break loop */ break; } /* Go to the next subtable */ MadtTable += SubTable->Length; } } /* Check if any I/O APIC controllers were found */ if(ControllerCount == 0) { /* No I/O APIC controllers found, return failure */ return STATUS_NOT_FOUND; } /* Return success */ return STATUS_SUCCESS; } /** * Gets the local APIC ID of the current processor. * * @return This routine returns the current processor's local APIC ID. * * @since XT 1.0 */ XTAPI ULONG HL::Pic::GetCpuApicId(VOID) { ULONG ApicId; /* Read APIC ID register */ ApicId = ReadApicRegister(APIC_ID); /* Return logical CPU ID depending on current APIC mode */ return (ApicMode == APIC_MODE_COMPAT) ? ((ApicId & 0xFFFFFFFF) >> APIC_XAPIC_LDR_SHIFT) : ApicId; } /** * Gets the I/O APIC controller information for the specified GSI. * * @param Gsi * Supplies the GSI to get the I/O APIC controller information for. * * @param Controller * Supplies a pointer to the memory area where the I/O APIC controller information will be stored. * * @param EntryNumber * Supplies a pointer to the memory area where the entry number will be stored. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Pic::GetIoApicController(IN ULONG Gsi, OUT PIOAPIC_DATA *Controller, OUT PULONG EntryNumber) { ULONG ControllerIndex; /* Iterate over all available I/O APIC controllers */ for(ControllerIndex = 0; ControllerIndex < ControllerCount; ControllerIndex++) { /* Check if the GSI belongs to this I/O APIC controller */ if(Gsi >= Controllers[ControllerIndex].GsiBase && Gsi < (Controllers[ControllerIndex].GsiBase + Controllers[ControllerIndex].LineCount)) { /* Return I/O APIC controller information */ *Controller = &Controllers[ControllerIndex]; *EntryNumber = (ULONG)(Gsi - Controllers[ControllerIndex].GsiBase); return STATUS_SUCCESS; } } /* GSI does not belong to any I/O APIC controller, return failure */ return STATUS_NOT_FOUND; } /** * Services the APIC Error interrupt, invoked when the APIC detects an internal hardware or message passing error. * * @param TrapFrame * Supplies a pointer to the hardware trap frame representing the interrupted execution context. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HL::Pic::HandleApicErrorInterrupt(IN PKTRAP_FRAME TrapFrame) { ULONG ErrorStatus; /* Write 0 to the ESR register to trigger an internal state update, then read the latched status */ WriteApicRegister(APIC_ESR, 0); ErrorStatus = (ULONG)ReadApicRegister(APIC_ESR); /* Log the detected hardware error */ DebugPrint(L"Caught APIC Error interrupt with ESR = 0x%08X\n", ErrorStatus); /* Acknowledge the interrupt to allow further interrupt delivery */ SendEoi(); } /** * Initializes the APIC interrupt controller. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Pic::InitializeApic(VOID) { APIC_SPURIOUS_REGISTER SpuriousRegister; APIC_BASE_REGISTER BaseRegister; APIC_LVT_REGISTER LvtRegister; ULONG CpuNumber; /* Check APIC support */ if(!CheckApicSupport()) { /* APIC is not supported, raise kernel panic */ DebugPrint(L"ERROR: Local APIC not present.\n"); KE::Crash::Panic(0x5D, CPUID_GET_STANDARD1_FEATURES, 0x0, 0x0, CPUID_FEATURES_EDX_APIC); } /* Determine APIC mode (xAPIC compatibility or x2APIC) */ if(CheckX2ApicSupport()) { /* Enable x2APIC mode */ ApicMode = APIC_MODE_X2APIC; } else { /* Fall back to xAPIC compatibility mode */ ApicMode = APIC_MODE_COMPAT; } /* Get current processor number */ CpuNumber = KE::Processor::GetCurrentProcessorNumber(); /* Enable the APIC */ BaseRegister.LongLong = AR::CpuFunctions::ReadModelSpecificRegister(APIC_LAPIC_MSR_BASE); BaseRegister.Enable = 1; BaseRegister.ExtendedMode = (ApicMode == APIC_MODE_X2APIC); BaseRegister.BootStrapProcessor = (CpuNumber == 0) ? 1 : 0; AR::CpuFunctions::WriteModelSpecificRegister(APIC_LAPIC_MSR_BASE, BaseRegister.LongLong); /* Mask all interrupts by raising Task Priority Register (TPR) */ WriteApicRegister(APIC_TPR, 0xFF); /* Perform initialization specific to xAPIC compatibility mode */ if(ApicMode == APIC_MODE_COMPAT) { /* Use Flat Model for destination format (not supported in x2APIC) */ WriteApicRegister(APIC_DFR, APIC_DF_FLAT); /* Set the logical APIC ID for this processor (read-only in x2APIC) */ WriteApicRegister(APIC_LDR, (1UL << CpuNumber) << 24); } /* Report the APIC ID to the kernel logic */ KE::Processor::RegisterHardwareId(GetCpuApicId()); /* Configure the spurious interrupt vector */ SpuriousRegister.Long = ReadApicRegister(APIC_SIVR); SpuriousRegister.Vector = APIC_VECTOR_SPURIOUS; SpuriousRegister.SoftwareEnable = 1; SpuriousRegister.CoreChecking = 0; WriteApicRegister(APIC_SIVR, SpuriousRegister.Long); /* Setup the LVT Error entry to deliver APIC errors on a dedicated vector */ WriteApicRegister(APIC_ERRLVTR, APIC_VECTOR_ERROR); /* Mask the APIC Timer */ LvtRegister.Long = 0; LvtRegister.Mask = 1; WriteApicRegister(APIC_TMRLVTR, LvtRegister.Long); /* Configure the performance counter overflow */ LvtRegister.Long = 0; LvtRegister.Mask = 0; LvtRegister.DeliveryMode = APIC_DM_FIXED; LvtRegister.TimerMode = 0; LvtRegister.TriggerMode = APIC_TGM_EDGE; LvtRegister.Vector = APIC_VECTOR_PERF; WriteApicRegister(APIC_PCLVTR, LvtRegister.Long); /* Configure the LINT0 pin */ LvtRegister.Long = 0; LvtRegister.Mask = 1; LvtRegister.DeliveryMode = APIC_DM_FIXED; LvtRegister.TimerMode = 0; LvtRegister.TriggerMode = APIC_TGM_EDGE; LvtRegister.Vector = APIC_VECTOR_SPURIOUS; WriteApicRegister(APIC_LINT0, LvtRegister.Long); /* Configure the LINT1 pin */ LvtRegister.Long = 0; LvtRegister.Mask = 0; LvtRegister.DeliveryMode = APIC_DM_NMI; LvtRegister.TimerMode = 0; LvtRegister.TriggerMode = APIC_TGM_EDGE; LvtRegister.Vector = APIC_VECTOR_NMI; WriteApicRegister(APIC_LINT1, LvtRegister.Long); /* Register interrupt handlers */ HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_ERROR, HandleApicErrorInterrupt); HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_PROFILE, HL::Irq::HandleProfileInterrupt); HL::Irq::RegisterInterruptHandler(APIC_VECTOR_SPURIOUS, (PVOID)ArHandleSpuriousInterrupt); /* Clear any pre-existing errors */ WriteApicRegister(APIC_ESR, 0); /* Re-enable all interrupts by lowering the Task Priority Register */ WriteApicRegister(APIC_TPR, 0x00); } /** * Initializes the global I/O APIC controller setup over the entire redirection span. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Pic::InitializeIOApic(VOID) { ULONG ControllerIndex, LineIndex, Vector, VersionRegister; IOAPIC_REDIRECTION_REGISTER Register; XTSTATUS Status; /* Detect I/O APIC controllers */ Status = DetectIoApicControllers(); if(Status != STATUS_SUCCESS) { DebugPrint(L"ERROR: I/O APIC Controller not present.\n"); KE::Crash::Panic(0x5D, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); } /* Iterate over all I/O APIC controllers */ ControllerIndex = 0; while(ControllerIndex < ControllerCount) { /* Map the I/O APIC controller memory into hardware space */ Status = MM::HardwarePool::MapHardwareMemory(Controllers[ControllerIndex].PhysicalAddress, 1, FALSE, (PVOID*)&Controllers[ControllerIndex].VirtualAddress); if(Status != STATUS_SUCCESS || Controllers[ControllerIndex].VirtualAddress == 0) { DebugPrint(L"ERROR: Failed to map I/O APIC Controller\n"); KE::Crash::Panic(0x0E, 0x0, 0x0, 0x0, 0x0); } /* Perform a memory barrier */ AR::CpuFunctions::MemoryBarrier(); AR::CpuFunctions::ReadWriteBarrier(); /* Read the version register and calculate the maximum number of redirection entries */ VersionRegister = ReadIOApicRegister(&Controllers[ControllerIndex], IOAPIC_VER); Controllers[ControllerIndex].LineCount = ((VersionRegister >> 16) & 0xFF) + 1; /* Set up the default redirection entry for this controller */ Register.LongLong = 0; Register.DeliveryMode = APIC_DM_FIXED; Register.DeliveryStatus = 0; Register.Destination = ReadIOApicRegister(&Controllers[ControllerIndex], IOAPIC_ID) >> 24; Register.DestinationMode = 0; Register.Mask = 1; Register.PinPolarity = 0; Register.RemoteIRR = 0; Register.Reserved = 0; Register.TriggerMode = APIC_TGM_EDGE; Register.Vector = IOAPIC_VECTOR_FREE; /* Propagate defaults across the array of potential handlers */ for(LineIndex = 0; LineIndex < Controllers[ControllerIndex].LineCount; LineIndex++) { /* Write default values into the redirection table */ WriteRedirectionEntry(&Controllers[ControllerIndex], LineIndex, Register); } /* Print information about the I/O APIC controller */ DebugPrint(L"Initialized I/O APIC Controller #%lu at 0x%llX (ID: %lu, GSI Base: %lu, Line Count: %lu)\n", ControllerIndex, Controllers[ControllerIndex].VirtualAddress, Controllers[ControllerIndex].Identifier, Controllers[ControllerIndex].GsiBase, Controllers[ControllerIndex].LineCount); /* Go to the next I/O APIC controller */ ControllerIndex++; } /* Assign initial clean state for mapping translations */ for(Vector = 0; Vector <= 255; Vector++) { /* Set vector to free */ MappedVectors[Vector] = IOAPIC_VECTOR_FREE; } } /** * Initializes the legacy PIC interrupt controller. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Pic::InitializeLegacyPic(VOID) { PIC_I8259_ICW1 Icw1; PIC_I8259_ICW2 Icw2; PIC_I8259_ICW3 Icw3; PIC_I8259_ICW4 Icw4; /* Initialize ICW1 for PIC1 port */ Icw1.Init = TRUE; Icw1.InterruptMode = EdgeTriggered; Icw1.InterruptVectorAddress = 0; Icw1.Interval = Interval8; Icw1.NeedIcw4 = TRUE; Icw1.OperatingMode = Cascade; HL::IoPort::WritePort8(PIC1_CONTROL_PORT, Icw1.Bits); /* Initialize ICW2 for PIC1 port */ Icw2.Bits = 0x00; HL::IoPort::WritePort8(PIC1_DATA_PORT, Icw2.Bits); /* Initialize ICW3 for PIC1 port */ Icw3.Bits = 0; Icw3.SlaveIrq2 = TRUE; HL::IoPort::WritePort8(PIC1_DATA_PORT, Icw3.Bits); /* Initialize ICW4 for PIC1 port */ Icw4.BufferedMode = NonBuffered; Icw4.EoiMode = NormalEoi; Icw4.Reserved = 0; Icw4.SpecialFullyNestedMode = FALSE; Icw4.SystemMode = New8086Mode; HL::IoPort::WritePort8(PIC1_DATA_PORT, Icw4.Bits); /* Mask all interrupts on PIC1 port */ HL::IoPort::WritePort8(PIC1_DATA_PORT, 0xFF); /* Initialize ICW1 for PIC2 port */ Icw1.Init = TRUE; Icw1.InterruptMode = EdgeTriggered; Icw1.InterruptVectorAddress = 0; Icw1.Interval = Interval8; Icw1.NeedIcw4 = TRUE; Icw1.OperatingMode = Cascade; HL::IoPort::WritePort8(PIC2_CONTROL_PORT, Icw1.Bits); /* Initialize ICW2 for PIC2 port */ Icw2.Bits = 0x08; HL::IoPort::WritePort8(PIC2_DATA_PORT, Icw2.Bits); /* Initialize ICW3 for PIC2 port */ Icw3.Bits = 0; Icw3.SlaveId = 2; HL::IoPort::WritePort8(PIC2_DATA_PORT, Icw3.Bits); /* Initialize ICW4 for PIC2 port */ Icw4.BufferedMode = NonBuffered; Icw4.EoiMode = NormalEoi; Icw4.Reserved = 0; Icw4.SpecialFullyNestedMode = FALSE; Icw4.SystemMode = New8086Mode; HL::IoPort::WritePort8(PIC2_DATA_PORT, Icw4.Bits); /* Mask all interrupts on PIC2 port */ HL::IoPort::WritePort8(PIC2_DATA_PORT, 0xFF); /* Register interrupt handler */ HL::Irq::RegisterInterruptHandler(PIC1_VECTOR_SPURIOUS, (PVOID)ArHandleSpuriousInterrupt); } /** * Initializes the (A)PIC interrupt controller. * * @return This routine does not return any value. * * @since XT 1.0 * * @todo Initialize APIC only when supported, otherwise fall back to legacy PIC. */ XTAPI VOID HL::Pic::InitializePic(VOID) { /* Initialize APIC */ InitializeApic(); /* Initialize legacy PIC */ InitializeLegacyPic(); } /** * Reads from the APIC register. * * @param Register * Supplies the APIC register to read from. * * @return This routine returns the value read from the APIC register. * * @since XT 1.0 */ XTFASTCALL ULONGLONG HL::Pic::ReadApicRegister(IN APIC_REGISTER Register) { if(ApicMode == APIC_MODE_X2APIC) { /* Read from x2APIC MSR */ return AR::CpuFunctions::ReadModelSpecificRegister((ULONG)(APIC_X2APIC_MSR_BASE + Register)); } else { /* Read from xAPIC */ return HL::IoRegister::ReadRegister32((PULONG)(APIC_BASE + (Register << 4))); } } /** * Reads from the I/O APIC register. * * @param Controller * Supplies the I/O APIC controller to read from. * * @param Register * Supplies the I/O APIC register to read from. * * @return This routine returns the value read from the given IO APIC register. * * @since XT 1.0 */ XTFASTCALL ULONG HL::Pic::ReadIOApicRegister(IN PIOAPIC_DATA Controller, IN UCHAR Register) { /* Write the target address into the index register */ HL::IoRegister::WriteRegister32((PULONG)(Controller->VirtualAddress + IOAPIC_IOREGSEL), Register); /* Fetch the resultant value from the data window */ return HL::IoRegister::ReadRegister32((PULONG)(Controller->VirtualAddress + IOAPIC_IOWIN)); } /** * Reads a configuration entry from the I/O APIC redirection table. * * @param Controller * Supplies the I/O APIC controller to read from. * * @param EntryNumber * Supplies the redirection table entry number to read. * * @return This routine returns the populated redirection table entry. * * @since XT 1.0 */ XTFASTCALL IOAPIC_REDIRECTION_REGISTER HL::Pic::ReadRedirectionEntry(IN PIOAPIC_DATA Controller, IN ULONG EntryNumber) { IOAPIC_REDIRECTION_REGISTER Register; ULONG Offset; /* Derive the offset corresponding to the index */ Offset = IOAPIC_REDTBL + (EntryNumber * IOAPIC_RTE_SIZE); /* Read the low and high portions mapping to the 64-bit construct */ Register.Base = ReadIOApicRegister(Controller, Offset); Register.Extended = ReadIOApicRegister(Controller, Offset + 1); /* Return the redirection table entry */ return Register; } /** * Resolves the GSI and flags for the specified IRQ. * * @param Irq * Supplies the IRQ number to get the GSI and flags for. * * @param Gsi * Supplies a pointer to the memory area where the GSI will be stored. * * @param Flags * Supplies a pointer to the memory area where the flags will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Pic::ResolveInterruptOverride(IN UCHAR Irq, OUT PULONG Gsi, OUT PUSHORT Flags) { ULONG Index; /* Iterate over all I/O APIC overrides */ for(Index = 0; Index < IrqOverrideCount; Index++) { /* Check if this IRQ has been overridden */ if(IrqOverrides[Index].SourceIrq == Irq) { /* Return overridden GSI and flags */ *Flags = IrqOverrides[Index].Flags; *Gsi = IrqOverrides[Index].GlobalSystemInterrupt; return; } } /* Return original IRQ number as GSI and no flags */ *Flags = 0; *Gsi = (ULONG)Irq; } /** * Sends a Broadcast IPI (Inter-Processor Interrupt) to all processors in the system. * * @param Vector * Supplies the hardware interrupt vector to trigger on the target processors. * * @param Self * Supplies a boolean value indicating the broadcast scope. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Pic::SendBroadcastIpi(IN ULONG Vector, IN BOOLEAN Self) { PKPROCESSOR_BLOCK CurrentProcessorBlock, TargetProcessorBlock; PACPI_SYSTEM_INFO SysInfo; BOOLEAN Interrupts; ULONG Index; /* Get the current processor block */ CurrentProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); if(CurrentProcessorBlock == NULLPTR) { /* Processor block not available, return */ return; } /* Get the ACPI system information */ HL::Acpi::GetSystemInformation(&SysInfo); /* Check whether interrupts are enabled */ Interrupts = AR::CpuFunctions::InterruptsEnabled(); /* Disable interrupts */ AR::CpuFunctions::ClearInterruptFlag(); /* Iterate over all logical CPUs */ for(Index = 0; Index < SysInfo->CpuCount; Index++) { /* Retrieve the target processor block by its Logical CPU Number */ TargetProcessorBlock = KE::Processor::GetProcessorBlock(Index); /* Only send to processors that exist and have successfully started */ if(TargetProcessorBlock != NULLPTR && TargetProcessorBlock->Started) { /* Check if this processor originated the broadcast */ if(TargetProcessorBlock->HardwareId == CurrentProcessorBlock->HardwareId) { /* Check if this is a self broadcast */ if(Self) { /* Dispatch the IPI to the current processor */ SendSelfIpi(Vector); } } else { /* Dispatch the IPI to the target processor */ SendIpi(TargetProcessorBlock->HardwareId, Vector, APIC_DM_FIXED, APIC_DSH_Destination, APIC_TGM_EDGE); } } } /* Check whether interrupts need to be re-enabled */ if(Interrupts) { /* Re-enable interrupts */ AR::CpuFunctions::SetInterruptFlag(); } } /** * Signals to the APIC that handling an interrupt is complete. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Pic::SendEoi(VOID) { /* Send APIC EOI */ WriteApicRegister(APIC_EOI, 0); } /** * Sends an IPI (Inter-Processor Interrupt) to the specified CPU. * * @param ApicId * Supplies a CPU APIC ID to send an IPI to. * * @param Vector * Supplies the IPI vector to send. * * @param DeliveryMode * Supplies the delivery mode for the IPI. * * @param DestinationShorthand * Supplies the shorthand. * * @param TriggerMode * Supplies the trigger mode (Edge or Level). * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Pic::SendIpi(IN ULONG ApicId, IN ULONG Vector, IN APIC_DM DeliveryMode, IN APIC_DSH DestinationShortHand, IN ULONG TriggerMode) { APIC_COMMAND_REGISTER Register; BOOLEAN Interrupts; /* Check whether interrupts are enabled */ Interrupts = AR::CpuFunctions::InterruptsEnabled(); /* Disable interrupts */ AR::CpuFunctions::ClearInterruptFlag(); /* Check current APIC mode and destination */ if(ApicMode == APIC_MODE_X2APIC && DestinationShortHand == APIC_DSH_Self) { /* In x2APIC mode, a dedicated Self-IPI register is used */ WriteApicRegister(APIC_SIPI, Vector); /* Check whether interrupts need to be re-enabled */ if(Interrupts) { /* Check whether interrupts need to be re-enabled */ AR::CpuFunctions::SetInterruptFlag(); } /* Nothing more to do */ return; } /* Prepare APIC command register struct */ Register.LongLong = 0; Register.DeliveryMode = DeliveryMode; Register.Destination = ApicId; Register.DestinationShortHand = DestinationShortHand; Register.Level = 1; Register.TriggerMode = TriggerMode; Register.Vector = Vector; /* Check current APIC mode */ if(ApicMode == APIC_MODE_X2APIC) { /* Set destination APIC ID */ Register.Long1 = ApicId; /* Send IPI using x2APIC mode */ WriteApicRegister(APIC_ICR0, Register.LongLong); } else { /* Wait for the APIC to clear the delivery status */ while((ReadApicRegister(APIC_ICR0) & 0x1000) != 0) { /* Yield the processor */ AR::CpuFunctions::YieldProcessor(); } /* In xAPIC compatibility mode, write the command to the ICR registers */ WriteApicRegister(APIC_ICR1, Register.Long1); WriteApicRegister(APIC_ICR0, Register.Long0); /* Check if this is a Self-IPI */ if(DestinationShortHand == APIC_DSH_Self) { /* Wait until the interrupt physically arrives in the requested state */ while((ReadApicRegister((APIC_REGISTER)(APIC_IRR + (Vector / 32))) & (1UL << (Vector % 32))) == 0) { /* Yield the processor */ AR::CpuFunctions::YieldProcessor(); } } } /* Check whether interrupts need to be re-enabled */ if(Interrupts) { /* Re-enable interrupts */ AR::CpuFunctions::SetInterruptFlag(); } } /** * Sends a Self-IPI (Inter-Processor Interrupt) to the current CPU. * * @param Vector * Supplies the IPI vector to send. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Pic::SendSelfIpi(IN ULONG Vector) { SendIpi(0, Vector, APIC_DM_FIXED, APIC_DSH_Self, APIC_TGM_EDGE); } /** * Translates a given Global System Interrupt (GSI) into an active system interrupt vector. * * @param Gsi * Supplies the GSI to translate. * * @return This routine returns the underlying associated system vector mapping. * * @since XT 1.0 */ XTFASTCALL UCHAR HL::Pic::TranslateGsiToVector(IN ULONG Gsi) { IOAPIC_REDIRECTION_REGISTER Register; PIOAPIC_DATA Controller; ULONG EntryNumber; XTSTATUS Status; /* Find the APIC controller for the GSI */ Status = GetIoApicController(Gsi, &Controller, &EntryNumber); if(Status != STATUS_SUCCESS) { /* GSI maps to an invalid controller, return free */ return IOAPIC_VECTOR_FREE; } /* Read the redirection table entry */ Register.Base = ReadIOApicRegister(Controller, IOAPIC_REDTBL + (EntryNumber * IOAPIC_RTE_SIZE)); /* Return the vector */ return (UCHAR)Register.Vector; } /** * Writes to the APIC register. * * @param Register * Supplies the APIC register to write to. * * @param Value * Supplies the value to write to the APIC register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID HL::Pic::WriteApicRegister(IN APIC_REGISTER Register, IN ULONGLONG Value) { if(ApicMode == APIC_MODE_X2APIC) { /* Write to x2APIC MSR */ AR::CpuFunctions::WriteModelSpecificRegister((ULONG)(APIC_X2APIC_MSR_BASE + Register), Value); } else { /* Write to xAPIC */ HL::IoRegister::WriteRegister32((PULONG)(APIC_BASE + (Register << 4)), Value); } } /** * Writes a value to the I/O APIC register. * * @param Controller * Supplies the I/O APIC controller to write to. * * @param Register * Supplies the I/O APIC register to write to. * * @param DataValue * Supplies the value to write to the designated I/O APIC register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID HL::Pic::WriteIOApicRegister(IN PIOAPIC_DATA Controller, IN UCHAR Register, IN ULONG DataValue) { /* Provide the index to the control port */ HL::IoRegister::WriteRegister32((PULONG)(Controller->VirtualAddress + IOAPIC_IOREGSEL), Register); /* Commit the value via the data port */ HL::IoRegister::WriteRegister32((PULONG)(Controller->VirtualAddress + IOAPIC_IOWIN), DataValue); } /** * Writes a configuration entry into the I/O APIC redirection table. * * @param Controller * Supplies the I/O APIC controller to write to. * * @param EntryNumber * Supplies the redirection table entry number to write. * * @param EntryData * Supplies the redirection table entry data to write. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID HL::Pic::WriteRedirectionEntry(IN PIOAPIC_DATA Controller, IN ULONG EntryNumber, IN IOAPIC_REDIRECTION_REGISTER EntryData) { ULONG Offset; /* Calculate the offset of the redirection entry */ Offset = IOAPIC_REDTBL + (EntryNumber * IOAPIC_RTE_SIZE); /* Mask the entry to prevent spurious interrupts */ WriteIOApicRegister(Controller, Offset, IOAPIC_RTE_MASKED); /* Write the lower and upper chunks of the entry */ WriteIOApicRegister(Controller, Offset + 1, EntryData.Extended); WriteIOApicRegister(Controller, Offset, EntryData.Base); } ================================================ FILE: xtoskrnl/hl/x86/rtc.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/x86/rtc.cc * DESCRIPTION: Hardware Real-Time Clock (RTC) support * DEVELOPERS: Aiken Harris */ #include /** * Queries the hardware Real-Time Clock (RTC) for the current date and time. * * @param Time * Supplies a pointer to a structure to receive the system time. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Rtc::GetRealTimeClock(OUT PTIME_FIELDS Time) { UCHAR Century1, Century2, CenturyRegister, RegisterB; TIME_FIELDS TimeProbe1, TimeProbe2; PACPI_FADT FadtTable; BOOLEAN PostMeridiem; XTSTATUS Status; ULONG Index; /* Locate the ACPI FADT table */ Status = HL::Acpi::GetAcpiTable(ACPI_FADT_SIGNATURE, (PACPI_DESCRIPTION_HEADER*)&FadtTable); if(Status == STATUS_SUCCESS && FadtTable && FadtTable->CenturyAlarmIndex) { /* Cache the dynamically provided Century register index */ CenturyRegister = FadtTable->CenturyAlarmIndex; } else { /* Century register is unavailable */ CenturyRegister = 0; Century1 = 0; Century2 = 0; } /* Read the RTC Status Register B to determine hardware data formats */ RegisterB = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_B); /* Assume failure */ Status = STATUS_UNSUCCESSFUL; /* Execute a maximum of 100 retries to obtain a stable RTC snapshot */ for(Index = 0; Index < 100; Index++) { /* Wait until the RTC hardware finishes any ongoing background updates */ while(HL::Firmware::ReadCmosRegister(CMOS_REGISTER_A) & CMOS_REGISTER_A_UPDATE_IN_PROGRESS) { /* Yield the processor */ AR::CpuFunctions::YieldProcessor(); } /* Latch the first sequential hardware time snapshot */ TimeProbe1.Hour = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_HOUR); TimeProbe1.Minute = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_MINUTE); TimeProbe1.Second = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_SECOND); TimeProbe1.Day = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_DAY); TimeProbe1.Month = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_MONTH); TimeProbe1.Year = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_YEAR); TimeProbe1.Weekday = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_WEEKDAY); /* Check if Century register is available */ if(CenturyRegister) { /* Read the corresponding Century register */ Century1 = HL::Firmware::ReadCmosRegister(CenturyRegister); } /* Wait until the RTC hardware finishes any ongoing background updates */ while(HL::Firmware::ReadCmosRegister(CMOS_REGISTER_A) & CMOS_REGISTER_A_UPDATE_IN_PROGRESS) { /* Yield the processor */ AR::CpuFunctions::YieldProcessor(); } /* Latch the second sequential hardware time snapshot for verification */ TimeProbe2.Hour = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_HOUR); TimeProbe2.Minute = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_MINUTE); TimeProbe2.Second = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_SECOND); TimeProbe2.Day = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_DAY); TimeProbe2.Month = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_MONTH); TimeProbe2.Year = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_YEAR); TimeProbe2.Weekday = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_WEEKDAY); /* Check if Century register is available */ if(CenturyRegister) { /* Read the corresponding Century register */ Century2 = HL::Firmware::ReadCmosRegister(CenturyRegister); } /* Compare both snapshots to guarantee data consistency */ if((TimeProbe1.Hour == TimeProbe2.Hour) && (TimeProbe1.Minute == TimeProbe2.Minute) && (TimeProbe1.Second == TimeProbe2.Second) && (TimeProbe1.Day == TimeProbe2.Day) && (TimeProbe1.Month == TimeProbe2.Month) && (TimeProbe1.Year == TimeProbe2.Year) && (TimeProbe1.Weekday == TimeProbe2.Weekday) && (Century1 == Century2)) { /* A stable time sample was acquired, break the loop */ Status = STATUS_SUCCESS; break; } } /* Copy the validated data into the output buffer */ Time->Hour = TimeProbe1.Hour; Time->Minute = TimeProbe1.Minute; Time->Second = TimeProbe1.Second; Time->Milliseconds = 0; Time->Day = TimeProbe1.Day; Time->Month = TimeProbe1.Month; Time->Year = TimeProbe1.Year; Time->Weekday = TimeProbe1.Weekday; /* Check if RTC is operating in 12-hour mode */ if(!(RegisterB & CMOS_REGISTER_B_24_HOUR)) { /* Cache the PM status and strip the hardware flag */ PostMeridiem = (Time->Hour & CMOS_RTC_POST_MERIDIEM) != 0; Time->Hour &= ~CMOS_RTC_POST_MERIDIEM; } /* Convert Binary-Coded Decimal (BCD) values to standard integers if necessary */ if(!(RegisterB & CMOS_REGISTER_B_BINARY)) { /* Decode all standard time fields */ Time->Hour = BCD_TO_DECIMAL(Time->Hour); Time->Minute = BCD_TO_DECIMAL(Time->Minute); Time->Second = BCD_TO_DECIMAL(Time->Second); Time->Day = BCD_TO_DECIMAL(Time->Day); Time->Month = BCD_TO_DECIMAL(Time->Month); Time->Year = BCD_TO_DECIMAL(Time->Year); Time->Weekday = BCD_TO_DECIMAL(Time->Weekday); /* Check if Century byte is available */ if(CenturyRegister) { /* Convert Century byte */ Century1 = BCD_TO_DECIMAL(Century1); } } /* Standardize hours into a strict 24-hour format */ if(!(RegisterB & CMOS_REGISTER_B_24_HOUR)) { /* Adjust for midnight and noon boundary cases */ if(Time->Hour == 12) { /* 12 AM evaluates to 00:00, 12 PM evaluates to 12:00 */ Time->Hour = PostMeridiem ? 12 : 0; } else { /* Add 12 hours for PM times */ Time->Hour += PostMeridiem ? 12 : 0; } } /* Merge the century offset with the 2-digit hardware year */ if(Century1 >= 19 && Century1 <= 30) { /* Utilize the hardware-provided century base */ Time->Year += (Century1 * 100); } else { /* Century byte is invalid; apply the sliding window */ Time->Year += (Time->Year > 80) ? 1900 : 2000; } /* Return status code */ return Status; } /** * Updates the hardware Real-Time Clock (RTC) with the provided date and time. * * @param Time * Supplies a pointer to a structure with populated data and time. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Rtc::SetRealTimeClock(IN PTIME_FIELDS Time) { UCHAR Century, CenturyRegister, RegisterB; TIME_FIELDS SystemTime; BOOLEAN PostMeridiem; PACPI_FADT FadtTable; XTSTATUS Status; /* Validate the input time boundaries against calendar limits */ if(Time->Hour > 23 || Time->Minute > 59 || Time->Second > 59 || Time->Day == 0 || Time->Day > 31 || Time->Month == 0 || Time->Month > 12 || Time->Weekday == 0 || Time->Weekday > 7) { /* Invalid time parameters, return error code */ return STATUS_INVALID_PARAMETER; } /* Assume Ante Meridiem */ PostMeridiem = FALSE; /* Extract local copy */ SystemTime.Hour = Time->Hour; SystemTime.Minute = Time->Minute; SystemTime.Second = Time->Second; SystemTime.Day = Time->Day; SystemTime.Month = Time->Month; SystemTime.Year = (Time->Year % 100); SystemTime.Weekday = Time->Weekday; Century = (UCHAR)(Time->Year / 100); /* Locate the ACPI FADT table */ Status = HL::Acpi::GetAcpiTable(ACPI_FADT_SIGNATURE, (PACPI_DESCRIPTION_HEADER*)&FadtTable); if(Status == STATUS_SUCCESS && FadtTable && FadtTable->CenturyAlarmIndex) { /* Cache the dynamically provided Century register index */ CenturyRegister = FadtTable->CenturyAlarmIndex; } else { /* Century register is unavailable */ CenturyRegister = 0; } /* Read the RTC Status Register B to determine hardware data formats */ RegisterB = HL::Firmware::ReadCmosRegister(CMOS_REGISTER_B); /* Format hours if the hardware is running in 12-hour mode */ if(!(RegisterB & CMOS_REGISTER_B_24_HOUR)) { /* Determine if the time is PM */ PostMeridiem = (SystemTime.Hour >= 12); /* Adjust for midnight and noon boundary cases */ if(SystemTime.Hour == 0) { /* Midnight evaluates to 12 AM */ SystemTime.Hour = 12; } else if(SystemTime.Hour > 12) { /* Post-noon hour */ SystemTime.Hour -= 12; } /* Convert to BCD first if needed and apply the hardware PM flag */ if(!(RegisterB & CMOS_REGISTER_B_BINARY)) { /* Encode to BCD */ SystemTime.Hour = DECIMAL_TO_BCD(SystemTime.Hour); } /* Apply the hardware PM flag to the highest bit */ if(PostMeridiem) { /* Set PM flag */ SystemTime.Hour |= CMOS_RTC_POST_MERIDIEM; } } else { /* 24-hour mode, simply encode to BCD if necessary */ if(!(RegisterB & CMOS_REGISTER_B_BINARY)) { /* Encode to BCD */ SystemTime.Hour = DECIMAL_TO_BCD(SystemTime.Hour); } } /* Convert remaining standard fields to BCD if necessary */ if(!(RegisterB & CMOS_REGISTER_B_BINARY)) { /* Encode all standard time fields */ SystemTime.Minute = DECIMAL_TO_BCD(SystemTime.Minute); SystemTime.Second = DECIMAL_TO_BCD(SystemTime.Second); SystemTime.Day = DECIMAL_TO_BCD(SystemTime.Day); SystemTime.Month = DECIMAL_TO_BCD(SystemTime.Month); SystemTime.Year = DECIMAL_TO_BCD(SystemTime.Year); SystemTime.Weekday = DECIMAL_TO_BCD((UCHAR)SystemTime.Weekday); /* Encode the Century byte */ Century = DECIMAL_TO_BCD(Century); } /* Freeze the RTC to prevent data tearing */ HL::Firmware::WriteCmosRegister(CMOS_REGISTER_B, RegisterB | CMOS_REGISTER_B_SET_CLOCK); /* Push the formatted time values into the hardware registers */ HL::Firmware::WriteCmosRegister(CMOS_REGISTER_HOUR, SystemTime.Hour); HL::Firmware::WriteCmosRegister(CMOS_REGISTER_MINUTE, SystemTime.Minute); HL::Firmware::WriteCmosRegister(CMOS_REGISTER_SECOND, SystemTime.Second); HL::Firmware::WriteCmosRegister(CMOS_REGISTER_DAY, SystemTime.Day); HL::Firmware::WriteCmosRegister(CMOS_REGISTER_MONTH, SystemTime.Month); HL::Firmware::WriteCmosRegister(CMOS_REGISTER_YEAR, SystemTime.Year); HL::Firmware::WriteCmosRegister(CMOS_REGISTER_WEEKDAY, SystemTime.Weekday); /* Check if Century register is available */ if(CenturyRegister) { /* Write the corresponding Century register */ HL::Firmware::WriteCmosRegister(CenturyRegister, Century); } /* Unfreeze the RTC */ HL::Firmware::WriteCmosRegister(CMOS_REGISTER_B, RegisterB); /* Return success status code */ return STATUS_SUCCESS; } ================================================ FILE: xtoskrnl/hl/x86/timer.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/x86/timer.cc * DESCRIPTION: Timer support for x86 (i686/AMD64) * DEVELOPERS: Aiken Harris */ #include /** * Calibrates the Local APIC timer frequency. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Timer::CalibrateApicTimer() { ULONG CurrentCount, Frequency, InitialCount; /* Get APIC timer frequency from the Core Crystal Clock */ if(TimerCapabilities.Art && TimerCapabilities.TimerFrequency != 0) { /* CCC available, use it as the source of APIC timer frequency */ Frequency = TimerCapabilities.TimerFrequency; } else { /* CCC unavailable, fallback to PIT calibration */ InitialCount = 0xFFFFFFFF; /* Load the initial count into the APIC Timer and begin the countdown */ HL::Pic::WriteApicRegister(APIC_TICR, InitialCount); /* Stall CPU execution for exactly 10 milliseconds */ StallExecution(10000); /* Read current tick count from APIC timer and clear APIC timer */ CurrentCount = HL::Pic::ReadApicRegister(APIC_TCCR); HL::Pic::WriteApicRegister(APIC_TICR, 0); /* Calculate APIC timer frequency based on ticks passed */ Frequency = (InitialCount - CurrentCount) * 100; /* Verify APIC timer frequency */ if(Frequency == 0) { /* Unable to calibrate APIC timer, return error */ return STATUS_UNSUCCESSFUL; } } /* Save APIC timer frequency */ TimerFrequency = Frequency; /* Print APIC timer frequency and return success */ DebugPrint(L"APIC Timer calibrated: %u Ticks/s\n", TimerFrequency); return STATUS_SUCCESS; } /** * Calibrates the Invariant TSC frequency. * * @return This routine returns the calculated TSC frequency in Hz. * * @since XT 1.0 */ XTAPI ULONGLONG HL::Timer::CalibrateTscCounter(VOID) { ULONGLONG InitialTickCount, FinalTickCount; ULONG TscAux; /* Get TSC frequency from the Core Crystal Clock */ if(TimerCapabilities.Art && TimerCapabilities.TimerFrequency != 0 && TimerCapabilities.TscDenominator != 0) { /* CCC available, use it as the source of TSC frequency */ return (TimerCapabilities.TimerFrequency * TimerCapabilities.TscNumerator) / TimerCapabilities.TscDenominator; } /* Latch the initial TSC value */ InitialTickCount = AR::CpuFunctions::ReadTimeStampCounterProcessor(&TscAux); /* Stall CPU execution for exactly 10 milliseconds */ StallExecution(10000); /* Read current tick count from TSC */ FinalTickCount = AR::CpuFunctions::ReadTimeStampCounterProcessor(&TscAux); /* Calculate the elapsed ticks over the 10ms window */ return (FinalTickCount - InitialTickCount) * 100; } /** * Calculates and configures the system time increments based on hardware timer properties. * * @param BaseFrequency * Supplies the base running frequency of the hardware timer in Hz. * * @param HardwareDivider * Supplies the programmed threshold/divider for the interrupt generation. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Timer::ConfigureTimeIncrement(IN ULONGLONG BaseFrequency, IN ULONGLONG HardwareDivider) { /* Calculate the time increment */ TimeIncrement = (ULONG)((10000000ULL * HardwareDivider) / BaseFrequency); /* Extract the fractional remainder */ FractionalIncrement = (ULONG)((10000000000ULL * HardwareDivider) / BaseFrequency) % 1000; RunningFraction = 0; /* Synchronize the kernel's global timekeeping state with the new resolution settings */ KE::SystemTime::SetTimeIncrement(TimeIncrement, TimeIncrement); } /** * Initializes the High Precision Event Timer (HPET) by discovering its ACPI configuration and mapping * its hardware registers into the kernel's virtual address space. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Timer::DetectHpet(VOID) { ULONGLONG CounterPeriod; PACPI_HPET HpetTable; PHPET_REGISTERS Hpet; XTSTATUS Status; /* Reset global HPET state */ HpetAddress = NULLPTR; HpetFrequency = 0; /* Retrieve the HPET table from the ACPI subsystem */ Status = HL::Acpi::GetAcpiTable(ACPI_HPET_SIGNATURE, (PACPI_DESCRIPTION_HEADER*)&HpetTable); if(Status != STATUS_SUCCESS || !HpetTable) { /* HPET is not present on this system, return error code */ return STATUS_NOT_FOUND; } /* Verify that the hardware registers are accessible via MMIO */ if(HpetTable->BaseAddress.AddressSpaceID != ACPI_ADDRESS_SPACE_MEMORY) { /* HPET base address not found, return error */ return STATUS_NOT_SUPPORTED; } /* Extract the physical base address from the Generic Address Structure (GAS) */ if(HpetTable->BaseAddress.Address.QuadPart == 0) { /* Invalid address provided by firmware, return error code */ return STATUS_UNSUCCESSFUL; } /* Map the physical hardware registers into the kernel's virtual memory space */ Status = MM::HardwarePool::MapHardwareMemory(HpetTable->BaseAddress.Address, 1, FALSE, &HpetAddress); if(Status != STATUS_SUCCESS || !HpetAddress) { /* Memory mapping failed, return error code */ return Status; } /* Configure the mapped memory region with Write-Through caching semantics */ MM::HardwarePool::MarkHardwareMemoryWriteThrough(HpetAddress, 1); /* Extract the main counter period */ Hpet = (PHPET_REGISTERS)HpetAddress; CounterPeriod = (Hpet->GeneralCapabilities >> 32) & 0xFFFFFFFF; /* Calculate the HPET operating frequency */ if(CounterPeriod != 0) { /* Convert femtoseconds per tick to ticks per second */ HpetFrequency = 1000000000000000ULL / CounterPeriod; } else { /* Assume the standard minimum HPET frequency (14.31818 MHz) */ HpetFrequency = 14318180; } /* Enable the HPET main counter and disable legacy replacement */ Hpet->GeneralConfiguration = (Hpet->GeneralConfiguration & ~HPET_CONFIG_LEGACY_REPLACEMENT) | HPET_CONFIG_ENABLE; /* Return success */ return STATUS_SUCCESS; } /** * Services the primary hardware clock interrupt, advancing the global system time, * maintaining local CPU thread quantums and performing profiling. * * @param TrapFrame * Supplies a pointer to the hardware trap frame representing the interrupted execution context. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HL::Timer::HandleClockInterrupt(IN PKTRAP_FRAME TrapFrame) { PKPROCESSOR_CONTROL_BLOCK Prcb; KRUNLEVEL RunLevel; ULONG Increment; /* Start the interrupt */ HL::Irq::BeginSystemInterrupt(CLOCK_LEVEL, &RunLevel); /* Check if PIT is the source of the interrupt */ if(ClockType == TimerPit) { /* Check if system clock initialized the rollover */ if(PitRollover != 0) { /* Update the PIT counter */ PitPerformanceCounter += PitRollover; } } /* Check if profiling is currently active */ if(ProfilingEnabled) { /* Retrieve the processor-specific control block */ Prcb = KE::Processor::GetCurrentProcessorControlBlock(); /* Trigger a profile sample if the countdown has expired */ if(Prcb->ProfilingCountdown == 0) { /* Dispatch the profile interrupt */ HL::Irq::HandleProfileInterrupt(TrapFrame); /* Reset the local countdown */ Prcb->ProfilingCountdown = ProfilingTicks; } /* Decrement the profiling countdown for the current hardware tick */ Prcb->ProfilingCountdown--; } /* Initialize the increment and update the fractional drift accumulator */ Increment = TimeIncrement; RunningFraction += FractionalIncrement; /* Check for fractional overflow */ if(RunningFraction >= 1000) { /* Apply the compensation tick and normalize the fractional remainder */ Increment++; RunningFraction -= 1000; } /* Route the timekeeping logic based on the underlying timer topology */ if(ClockType == TimerLapic) { /* Restrict global system time updates exclusively to the Bootstrap Processor */ if(KE::Processor::GetCurrentProcessorNumber() == 0) { /* Advance the global system time */ KE::SystemTime::UpdateSystemTime(TrapFrame, Increment, RunLevel); } else { /* Limit Application Processors (APs) to update runtimes */ KE::Dispatcher::UpdateRunTime(TrapFrame, RunLevel); } } else { /* Advance the global system time */ KE::SystemTime::UpdateSystemTime(TrapFrame, Increment, RunLevel); /* Broadcast an IPI to awaken all APs for local quantum updates */ HL::Pic::SendBroadcastIpi(APIC_VECTOR_CLOCK_IPI, FALSE); } /* End the interrupt */ HL::Irq::EndInterrupt(TrapFrame, RunLevel); } /** * Services the inter-processor clock interrupt, maintaining local CPU thread quantums and performing profiling. * * @param TrapFrame * Supplies a pointer to the hardware trap frame representing the interrupted execution context. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HL::Timer::HandleClockIpiInterrupt(IN PKTRAP_FRAME TrapFrame) { PKPROCESSOR_CONTROL_BLOCK Prcb; KRUNLEVEL RunLevel; /* Start the interrupt */ HL::Irq::BeginSystemInterrupt(CLOCK_LEVEL, &RunLevel); /* Check if profiling is currently active */ if(ProfilingEnabled) { /* Retrieve the processor-specific control block */ Prcb = KE::Processor::GetCurrentProcessorControlBlock(); /* Trigger a profile sample if the countdown has expired */ if(Prcb->ProfilingCountdown == 0) { /* Dispatch the profile interrupt */ HL::Irq::HandleProfileInterrupt(TrapFrame); /* Reset the local countdown */ Prcb->ProfilingCountdown = ProfilingTicks; } /* Decrement the profiling countdown for the current hardware tick */ Prcb->ProfilingCountdown--; } /* Call the kernel to update runtimes */ KE::Dispatcher::UpdateRunTime(TrapFrame, RunLevel); /* End the interrupt */ HL::Irq::EndInterrupt(TrapFrame, RunLevel); } /** * Initializes and calibrates the Local APIC Timer. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Timer::InitializeApicTimer(VOID) { APIC_LVT_REGISTER LvtRegister; XTSTATUS Status; ULONG Divider; /* Set APIC timer to divide by 1 */ HL::Pic::WriteApicRegister(APIC_TDCR, TIMER_DivideBy1); /* Calibrate the APIC timer */ Status = CalibrateApicTimer(); if(Status != STATUS_SUCCESS) { /* APIC calibration failed, return error code */ return Status; } /* Calculate the hardware threshold */ Divider = TimerFrequency / 1000; /* Program the APIC timer for periodic mode */ LvtRegister.Long = 0; LvtRegister.Mask = 0; LvtRegister.TimerMode = 1; LvtRegister.DeliveryMode = APIC_DM_FIXED; LvtRegister.TriggerMode = APIC_TGM_EDGE; LvtRegister.Vector = APIC_VECTOR_CLOCK; HL::Pic::WriteApicRegister(APIC_TMRLVTR, LvtRegister.Long); /* Jump-start the heartbeat */ HL::Pic::WriteApicRegister(APIC_TICR, Divider); /* Configure the kernel timekeeping abstractions based on calibrated APIC metrics */ HL::Timer::ConfigureTimeIncrement(TimerFrequency, Divider); /* Return success */ return STATUS_SUCCESS; } /** * Initializes the High Precision Event Timer (HPET) Timer. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Timer::InitializeHpetTimer(VOID) { ULONGLONG ClockPeriodTicks, TicksPerMillisecond; PHPET_REGISTERS Hpet; /* Ensure the HPET hardware registers are successfully mapped */ if(!HpetAddress) { /* The hardware mapping is not present, return error code */ return STATUS_UNSUCCESSFUL; } /* Cast the mapped virtual address to the HPET hardware register */ Hpet = (PHPET_REGISTERS)HpetAddress; /* Halt the main counter and disable legacy routing */ Hpet->GeneralConfiguration &= ~(HPET_CONFIG_ENABLE | HPET_CONFIG_LEGACY_REPLACEMENT); /* Reset the main counter to a known baseline */ Hpet->MainCounterValue = 0; /* Calculate the required hardware ticks for a standard 1-millisecond system clock interval */ TicksPerMillisecond = HpetFrequency / 1000; ClockPeriodTicks = TicksPerMillisecond * 1; /* Configure Comparator 0 for periodic mode with interrupt enable */ Hpet->Timers[0].Configuration |= (HPET_TIMER_CONFIG_ENABLED | HPET_TIMER_CONFIG_PERIODIC | HPET_TIMER_CONFIG_VALUE_ACCUMULATOR); /* Write the initial comparator value */ Hpet->Timers[0].Comparator = ClockPeriodTicks; /* Write the periodic interval into the accumulator */ Hpet->Timers[0].Comparator = ClockPeriodTicks; /* Enable the main counter and activate legacy replacement routing */ Hpet->GeneralConfiguration |= (HPET_CONFIG_ENABLE | HPET_CONFIG_LEGACY_REPLACEMENT); /* Configure the kernel timekeeping abstractions based on HPET metrics */ ConfigureTimeIncrement(HpetFrequency, ClockPeriodTicks); /* Route the IRQ 0 to the primary system clock vector */ HL::Pic::AllocateSystemInterrupt(0, CLOCK_LEVEL, APIC_VECTOR_CLOCK); /* Return success */ return STATUS_SUCCESS; } /** * Initializes the legacy Programmable Interval Timer (PIT). * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS HL::Timer::InitializePitTimer(VOID) { UCHAR LowByte, HighByte; ULONG Divider; /* Set the target frequency (1000 Hz) and calculate the required hardware divider */ Divider = PIT_BASE_FREQUENCY / 1000; /* Clamp the calculated divider to prevent 16-bit hardware overflow */ if(Divider > 65535) { /* Cap the maximum possible interval */ Divider = 65535; } else if(Divider < 1) { /* Enforce a minimum hardware divider */ Divider = 1; } /* Persist the calculated divider into a global state */ PitRollover = Divider; /* Split the 16-bit divider into an independent LSB and MSB */ LowByte = (UCHAR)(Divider & 0xFF); HighByte = (UCHAR)((Divider >> 8) & 0xFF); /* Configure Channel 0 for LSB/MSB access, Mode 2 */ HL::IoPort::WritePort8(PIT_COMMAND_PORT, PIT_CMD_CHANNEL0 | PIT_CMD_ACCESS_LOWBYTE_HIGHBYTE | PIT_MODE2_RATE_GENERATOR); /* Transmit the Least Significant Byte (LSB) */ HL::IoPort::WritePort8(PIT_DATA_PORT0, LowByte); /* Transmit the Most Significant Byte (MSB) */ HL::IoPort::WritePort8(PIT_DATA_PORT0, HighByte); /* Configure the kernel timekeeping abstractions based on legacy PIT metrics */ ConfigureTimeIncrement(PIT_BASE_FREQUENCY, Divider); /* Route the standard PIT IRQ 0 to the primary system clock vector */ HL::Pic::AllocateSystemInterrupt(0, CLOCK_LEVEL, APIC_VECTOR_CLOCK); /* Return success */ return STATUS_SUCCESS; } /** * Performs the primary initialization of the system timer. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Timer::InitializeTimer(VOID) { XTSTATUS Status; /* Probe hardware capabilities */ ProbeTimerType(); /* Check if a suitable hardware timer was selected */ if(TimerRoutines.InitializeClock) { /* Proceed with system clock initialization */ Status = TimerRoutines.InitializeClock(); if(Status != STATUS_SUCCESS) { /* System cannot operate without a functional system clock interrupt */ KE::Crash::Panic(0); } } /* Set the default system profile interval */ HL::Timer::SetProfileInterval(1000); /* Ensure the profile interrupt generation is explicitly disabled */ StopProfileInterrupt(ProfileXtKernel); /* Register the system clock interrupt handler */ HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_CLOCK, HandleClockInterrupt); HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_CLOCK_IPI, HandleClockIpiInterrupt); } /** * Performs an initial Timer initialization, discovering hardware and routing the Timer Dispatch table. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Timer::ProbeTimerType(VOID) { PACPI_TIMER_INFO AcpiTimerInfo; WCHAR ParameterValue[16]; XTSTATUS Status; /* Enumerate hardware timing capabilities */ QueryTimerCapabilities(); /* Discover and map the High Precision Event Timer */ Status = DetectHpet(); if(Status != STATUS_SUCCESS) { /* Diagnostic warning upon HPET subsystem initialization failure */ DebugPrint(L"TIMER: HPET initialization failed or HPET not present\n"); } /* Initialize the hardware selection states */ ClockType = TimerNone; TimerType = TimerNone; /* Query the kernel boot environment for a user-specified system clock override */ if(KE::BootInformation::GetKernelParameterValue(L"CLOCK", ParameterValue, 16) == STATUS_SUCCESS) { /* Evaluate the boot parameter string */ if(RTL::WideString::FindWideStringInsensitive(ParameterValue, L"HPET")) { /* Designate the HPET */ ClockType = TimerHpet; } else if(RTL::WideString::FindWideStringInsensitive(ParameterValue, L"LAPIC")) { /* Designate the Local APIC */ ClockType = TimerLapic; } else if(RTL::WideString::FindWideStringInsensitive(ParameterValue, L"PIT")) { /* Designate the legacy PIT */ ClockType = TimerPit; } } /* Query the kernel boot environment for a user-specified performance counter override */ if(KE::BootInformation::GetKernelParameterValue(L"TIMER", ParameterValue, 16) == STATUS_SUCCESS) { /* Evaluate the boot parameter string */ if(RTL::WideString::FindWideStringInsensitive(ParameterValue, L"ACPI") || RTL::WideString::FindWideStringInsensitive(ParameterValue, L"PM")) { /* Designate the ACPI PM Timer */ TimerType = TimerAcpiPm; } else if(RTL::WideString::FindWideStringInsensitive(ParameterValue, L"HPET")) { /* Designate the HPET */ TimerType = TimerHpet; } else if(RTL::WideString::FindWideStringInsensitive(ParameterValue, L"PIT")) { /* Designate the legacy PIT */ TimerType = TimerPit; } else if(RTL::WideString::FindWideStringInsensitive(ParameterValue, L"TSC")) { /* Designate the Invariant TSC */ TimerType = TimerTsc; } } /* Verify the hardware viability of the requested system clock */ if(ClockType != TimerNone && !ValidateTimerSupport(ClockType, TRUE)) { /* Invalidate the clock selection upon hardware validation failure */ DebugPrint(L"TIMER: Requested system clock [%d] unavailable\n", ClockType); ClockType = TimerNone; } /* Verify the hardware viability of the requested performance counter */ if(TimerType != TimerNone && !ValidateTimerSupport(TimerType, FALSE)) { /* Invalidate the counter selection upon hardware validation failure */ DebugPrint(L"TIMER: Requested hardware counter [%d] unavailable\n", TimerType); TimerType = TimerNone; } /* Execute the autonomous hardware selection for the system clock */ if(ClockType == TimerNone) { /* Probe system clock suitability */ if(ValidateTimerSupport(TimerLapic, TRUE)) { /* Select the Local APIC */ ClockType = TimerLapic; } else if(ValidateTimerSupport(TimerHpet, TRUE)) { /* Select the HPET */ ClockType = TimerHpet; } else { /* Fallback to the legacy PIT */ ClockType = TimerPit; } } /* Execute the autonomous hardware selection for the performance counter */ if(TimerType == TimerNone) { /* Probe the performance counter suitability */ if(ValidateTimerSupport(TimerTsc, FALSE)) { /* Select the Invariant TSC */ TimerType = TimerTsc; } else if(ValidateTimerSupport(TimerHpet, FALSE)) { /* Select the HPET */ TimerType = TimerHpet; } else if(ValidateTimerSupport(TimerAcpiPm, FALSE)) { /* Select the ACPI PM Timer */ TimerType = TimerAcpiPm; } else { /* Fallback to the legacy PIT */ TimerType = TimerPit; } } /* Retrieve the ACPI PM Timer hardware configuration */ HL::Acpi::GetAcpiTimerInfo(&AcpiTimerInfo); /* Determine if the ACPI PM Timer port is physically provisioned */ if(AcpiTimerInfo->TimerPort != 0) { /* Temporarily route execution stalls through the active ACPI PM hardware */ TimerRoutines.StallExecution = StallExecutionAcpiPm; } else { /* Temporarily route execution stalls through the legacy PIT hardware */ TimerRoutines.StallExecution = StallExecutionPit; } /* Dispatch the initialization routines based on the resolved system clock */ switch(ClockType) { case TimerLapic: /* Register the Local APIC initialization handler */ TimerRoutines.InitializeClock = InitializeApicTimer; TimerRoutines.SetClockRate = SetClockRateApic; DebugPrint(L"System Clock: Local APIC Timer (ARAT), "); break; case TimerHpet: /* Register the HPET comparator initialization handler */ TimerRoutines.InitializeClock = InitializeHpetTimer; TimerRoutines.SetClockRate = NULLPTR; DebugPrint(L"System Clock: HPET Comparator, "); break; default: /* Register the legacy PIT initialization handler */ TimerRoutines.InitializeClock = InitializePitTimer; TimerRoutines.SetClockRate = NULLPTR; DebugPrint(L"System Clock: Legacy PIT, "); break; } /* Dispatch the routines and configure baseline frequencies for the performance counter */ switch(TimerType) { case TimerTsc: /* Register the TSC */ PerformanceFrequency = CalibrateTscCounter(); TimerRoutines.QueryPerformanceCounter = QueryPerformanceCounterTsc; TimerRoutines.StallExecution = StallExecutionTsc; DebugPrint(L"Performance Counter: Invariant TSC @ %lluHz\n", PerformanceFrequency); break; case TimerHpet: /* Register the HPET */ PerformanceFrequency = HpetFrequency; TimerRoutines.QueryPerformanceCounter = QueryPerformanceCounterHpet; TimerRoutines.StallExecution = StallExecutionHpet; DebugPrint(L"Performance Counter: HPET @ %lluHz\n", PerformanceFrequency); break; case TimerAcpiPm: /* Register the ACPI PM */ PerformanceFrequency = 3579545; TimerRoutines.QueryPerformanceCounter = QueryPerformanceCounterAcpiPm; TimerRoutines.StallExecution = StallExecutionAcpiPm; KeInitializeSpinLock(&PerformanceCounterLock); DebugPrint(L"Performance Counter: ACPI PM Timer\n"); break; default: /* Register the legacy PIT */ PerformanceFrequency = 1193182; TimerRoutines.QueryPerformanceCounter = QueryPerformanceCounterPit; TimerRoutines.StallExecution = StallExecutionPit; KeInitializeSpinLock(&PerformanceCounterLock); DebugPrint(L"Performance Counter: Legacy PIT\n"); break; } } /** * Retrieves the current value of the high-resolution performance counter. * * @param PerformanceFrequency * Suplies an optional pointer to a variable that receives the performance counter frequency in Hz. * * @return This routine returns the current 64-bit monotonic tick count. * * @since XT 1.0 */ XTAPI LARGE_INTEGER HL::Timer::QueryPerformanceCounter(OUT PLARGE_INTEGER Frequency) { LARGE_INTEGER CurrentCounter; /* Check if the caller requested the frequency */ if(Frequency) { /* Assign the cached hardware frequency */ Frequency->QuadPart = PerformanceFrequency; } /* Dispatch to the specific hardware implementation */ CurrentCounter.QuadPart = TimerRoutines.QueryPerformanceCounter(); /* Return the retrieved timestamp */ return CurrentCounter; } /** * Queries the current value of the ACPI Power Management Timer. * * @return This routine returns the current ACPI timer tick count. * * @since XT 1.0 */ XTAPI ULONGLONG HL::Timer::QueryPerformanceCounterAcpiPm(VOID) { PACPI_TIMER_INFO AcpiTimerInfo; ULONG CurrentValue; /* Retrieve the ACPI Timer configuration */ HL::Acpi::GetAcpiTimerInfo(&AcpiTimerInfo); /* Raise RunLevel to DISPATCH_LEVEL and acquire spinlock */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::SpinLockGuard SpinLockGuard(&PerformanceCounterLock); /* Read the current hardware value and apply the bitmask */ CurrentValue = HL::IoPort::ReadPort32(AcpiTimerInfo->TimerPort) & AcpiTimerInfo->MsbMask; /* Calculate delta, accumulate the results and update last value for the next call */ SystemPerformanceCounter += (CurrentValue - AcpiPmPerformanceCounter) & AcpiTimerInfo->MsbMask; AcpiPmPerformanceCounter = CurrentValue; /* Return the accumulated value */ return SystemPerformanceCounter; } /** * Queries the current value of the High Precision Event Timer (HPET). * * @return This routine returns the current HPET main counter value. * * @since XT 1.0 */ XTAPI ULONGLONG HL::Timer::QueryPerformanceCounterHpet(VOID) { /* Perform a direct MMIO read from the register address */ return ((PHPET_REGISTERS)HpetAddress)->MainCounterValue; } /** * Queries the current value of the Legacy PIT. * * @return This routine returns the interpolated tick count. * * @since XT 1.0 */ XTAPI ULONGLONG HL::Timer::QueryPerformanceCounterPit(VOID) { ULONG ClockDelta, CounterValue; ULONGLONG PerformanceCounter; /* Check if system clock initialized the rollover */ if(PitRollover == 0) { /* Return the baseline counter value */ return SystemPerformanceCounter; } /* Raise RunLevel to DISPATCH_LEVEL and acquire spinlock */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::SpinLockGuard SpinLockGuard(&PerformanceCounterLock); /* Repeatedly sample the global tick count and the hardware counter */ do { /* Get the current global performance tick updated by ISR */ PerformanceCounter = PitPerformanceCounter; /* Send the LATCH command to freeze value in the PIT buffer */ HL::IoPort::WritePort8(PIT_COMMAND_PORT, 0x00); /* Read the remaining count from the data port */ CounterValue = HL::IoPort::ReadPort8(PIT_DATA_PORT0) | (HL::IoPort::ReadPort8(PIT_DATA_PORT0) << 8); } while(PerformanceCounter != PitPerformanceCounter); /* Clamp the value in case of a hardware glitch right at the rollover point */ if(CounterValue > PitRollover) { /* Force the sampled counter value to the maximum programmed reload threshold */ CounterValue = PitRollover; } /* Calculate how many ticks have passed since the last interrupt */ ClockDelta = PitRollover - CounterValue; /* Synthesize the final high-precision timestamp */ PerformanceCounter += ClockDelta; /* Guard against time drifting backward */ if(PerformanceCounter < SystemPerformanceCounter) { /* Compensate missing interrupt */ PerformanceCounter += PitRollover; } /* Update the last recorded counter */ SystemPerformanceCounter = PerformanceCounter; /* Return the timestamp */ return PerformanceCounter; } /** * Queries the current value of the Time Stamp Counter (TSC). * * @return This routine returns the current invariant TSC tick count. * * @since XT 1.0 */ XTAPI ULONGLONG HL::Timer::QueryPerformanceCounterTsc(VOID) { ULONG TscAux; /* Retrieve the timestamp */ return AR::CpuFunctions::ReadTimeStampCounterProcessor(&TscAux); } /** * Probes the processor via CPUID to detect available modern timing and clock generation features. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Timer::QueryTimerCapabilities(VOID) { PKPROCESSOR_CONTROL_BLOCK Prcb; CPUID_REGISTERS CpuRegisters; ULONG MaxStandardLeaf; /* Get current processor control block */ Prcb = KE::Processor::GetCurrentProcessorControlBlock(); /* Set timer capabilities based on supported CPU features */ TimerCapabilities.Arat = (Prcb->CpuId.FeatureBits & KCF_ARAT) != 0; TimerCapabilities.InvariantTsc= (Prcb->CpuId.ExtendedFeatureBits & KCF_INVARIANT_TSC) != 0; TimerCapabilities.RDTSCP = (Prcb->CpuId.ExtendedFeatureBits & KCF_RDTSCP) != 0; TimerCapabilities.TscDeadline = (Prcb->CpuId.FeatureBits & KCF_TSC_DEADLINE) != 0; /* Query maximum standard CPUID leaf */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_VENDOR_STRING; AR::CpuFunctions::CpuId(&CpuRegisters); MaxStandardLeaf = CpuRegisters.Eax; /* Check Always Running Timer - ART if leaf supported */ if(MaxStandardLeaf >= CPUID_GET_TSC_CRYSTAL_CLOCK) { /* Query the Time Stamp Counter and Core Crystal Clock information CPUID leaf */ RTL::Memory::ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_TSC_CRYSTAL_CLOCK; AR::CpuFunctions::CpuId(&CpuRegisters); /* Verify Always Running Timer support */ if(CpuRegisters.Eax != 0 && CpuRegisters.Ebx != 0) { /* Mark the ART as supported */ TimerCapabilities.Art = TRUE; /* Save the TSC scaling ratios */ TimerCapabilities.TscDenominator = CpuRegisters.Eax; TimerCapabilities.TscNumerator = CpuRegisters.Ebx; /* Check if ECX contains the nominal frequency of the core crystal clock */ if(CpuRegisters.Ecx != 0) { /* Save the base frequency for the APIC Timer */ TimerCapabilities.TimerFrequency = CpuRegisters.Ecx; } } } } /** * Requests a dynamic adjustment of the system clock resolution. * * @param Rate * Supplies the requested clock rate change in 100-nanosecond units. * * @return This routine returns the actual clock rate granted by the hardware. * * @since XT 1.0 */ XTAPI ULONG HL::Timer::SetClockRate(IN ULONG Rate) { ULONG HardwareRate; /* Validate and clamp the clock rate against architectural limits */ if(Rate < HL_MINIMUM_CLOCK_RATE) { /* Enforce minimum resolution to prevent system-wide interrupt storms */ Rate = HL_MINIMUM_CLOCK_RATE; } else if(Rate > HL_MAXIMUM_CLOCK_RATE) { /* Cap the clock rate to ensure responsiveness */ Rate = HL_MAXIMUM_CLOCK_RATE; } /* Check if the active hardware backend supports dynamic rate scaling */ if(TimerRoutines.SetClockRate) { /* Dispatch the reprogramming request */ HardwareRate = TimerRoutines.SetClockRate(Rate); } else { /* Fallback to the current fixed rate as scaling is unsupported */ HardwareRate = TimeIncrement; } /* Return the actual clock rate set */ return HardwareRate; } /** * Adjusts the Local APIC Timer frequency to match the requested resolution. * * @param Rate * Supplies the requested clock rate change in 100-nanosecond units. * * @return This routine returns the actual clock rate granted by the hardware. * * @since XT 1.0 */ XTAPI ULONG HL::Timer::SetClockRateApic(ULONG Rate) { ULONG NewDivider; BOOLEAN Interrupts; /* TODO: Implement IPI broadcast to synchronize all cores in SMP mode */ UNIMPLEMENTED; /* Calculate the hardware-specific tick count for the requested rate */ NewDivider = (ULONG)(((ULONGLONG)TimerFrequency * Rate) / 10000000ULL); /* Prevent an invalid zero-count state */ if(NewDivider == 0) { /* Enforce a single-tick */ NewDivider = 1; } /* Check whether interrupts are enabled */ Interrupts = AR::CpuFunctions::InterruptsEnabled(); /* Disable interrupts */ AR::CpuFunctions::ClearInterruptFlag(); /* Commit the new divider to the TICR register */ HL::Pic::WriteApicRegister(APIC_TICR, NewDivider); /* Synchronize the kernel's timekeeping math with the new hardware state */ ConfigureTimeIncrement(TimerFrequency, NewDivider); /* Check whether interrupts need to be re-enabled */ if(Interrupts) { /* Re-enable interrupts */ AR::CpuFunctions::SetInterruptFlag(); } /* Return the actual clock rate set */ return TimeIncrement; } /** * Sets the profile interrupt interval. The interval may be bounded by hardware capabilities. * * @param Interval * Supplies the requested profile interval in 100-nanosecond units. * * @return This routine returns the actual profile interval that was set. * * @since XT 1.0 */ XTAPI ULONG_PTR HL::Timer::SetProfileInterval(IN ULONG_PTR Interval) { /* Validate and bound the requested profile interval against hardware limits */ if(Interval < MIN_PROFILE_INTERVAL) { /* Enforce the minimum profile interval limit */ Interval = MIN_PROFILE_INTERVAL; } else if(Interval > MAX_PROFILE_INTERVAL) { /* Enforce the maximum profile interval limit */ Interval = MAX_PROFILE_INTERVAL; } /* Calculate the required number of ticks for the requested interval */ ProfilingTicks = (ULONG)(Interval / 10000); /* Return the actual interval */ return Interval; } /** * Stalls the CPU execution for a specified duration. * * @param MicroSeconds * Supplies the number of microseconds to stall execution. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Timer::StallExecution(IN ULONG MicroSeconds) { /* Dispatch the stall request */ TimerRoutines.StallExecution(MicroSeconds); } /** * Stalls the CPU execution for a specified duration using the ACPI Power Management Timer. * * @param MicroSeconds * Supplies the number of microseconds to stall execution. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Timer::StallExecutionAcpiPm(IN ULONG MicroSeconds) { PACPI_TIMER_INFO AcpiTimerInfo; ULONG StartTick, CurrentTick, Delta, TicksElapsed; ULONGLONG TargetTicks; /* Validate input parameter */ if(MicroSeconds == 0) { /* Nothing to do */ return; } else if(MicroSeconds > 3000000) { /* Cap execution stall to 3 seconds */ MicroSeconds = 3000000; } /* Retrieve the ACPI PM Timer hardware configuration */ HL::Acpi::GetAcpiTimerInfo(&AcpiTimerInfo); /* Calculate the target number of ticks based on the standard ACPI PM frequency */ TargetTicks = ((ULONGLONG)MicroSeconds * 3579545ULL) / 1000000ULL; TicksElapsed = 0; /* Sample the initial hardware tick count and apply the hardware-specific bitmask */ StartTick = HL::IoPort::ReadPort32(AcpiTimerInfo->TimerPort) & AcpiTimerInfo->MsbMask; /* Spin the processor until the accumulated hardware ticks reach the calculated target */ while(TicksElapsed < TargetTicks) { /* Sample the current hardware tick count */ CurrentTick = HL::IoPort::ReadPort32(AcpiTimerInfo->TimerPort) & AcpiTimerInfo->MsbMask; /* Calculate the tick delta */ Delta = (CurrentTick - StartTick) & AcpiTimerInfo->MsbMask; /* Accumulate the elapsed ticks and advance the start marker */ TicksElapsed += Delta; StartTick = CurrentTick; /* Issue a PAUSE instruction to relieve memory bus contention */ AR::CpuFunctions::YieldProcessor(); } } /** * Stalls the CPU execution for a specified duration (maximum 3 seconds) using the High Precision Event Timer (HPET). * * @param MicroSeconds * Supplies the number of microseconds to stall execution. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Timer::StallExecutionHpet(IN ULONG MicroSeconds) { PHPET_REGISTERS Hpet; ULONGLONG StartTick, TargetTicks; /* Validate input parameter */ if(MicroSeconds == 0) { /* Nothing to do */ return; } else if(MicroSeconds > 3000000) { /* Cap execution stall to 3 seconds */ MicroSeconds = 3000000; } /* Cast the mapped virtual address to the HPET hardware register */ Hpet = (PHPET_REGISTERS)HpetAddress; /* Calculate target ticks based on HPET frequency */ TargetTicks = ((ULONGLONG)MicroSeconds * PerformanceFrequency) / 1000000ULL; StartTick = Hpet->MainCounterValue; /* Spin until the elapsed ticks reach the target */ while((Hpet->MainCounterValue - StartTick) < TargetTicks) { /* Issue a PAUSE instruction to relieve memory bus contention */ AR::CpuFunctions::YieldProcessor(); } } /** * Stalls the CPU execution for a specified duration (maximum 3 seconds) using the legacy PIT timer. * * @param MicroSeconds * Specifies the number of microseconds to stall execution. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Timer::StallExecutionPit(IN ULONG MicroSeconds) { USHORT CurrentCount, PreviousCount; ULONG TargetTicks, TickCounter; UCHAR Port61State; /* Validate input parameter */ if(MicroSeconds == 0) { /* Nothing to do */ return; } else if(MicroSeconds > 3000000) { /* Cap execution stall to 3 seconds */ MicroSeconds = 3000000; } /* Convert microseconds to PIT ticks using exact frequency arithmetic */ TargetTicks = (ULONG)(((ULONGLONG)MicroSeconds * 1193182ULL) / 1000000ULL); TickCounter = 0; /* Save the current state of System Control Port B */ Port61State = HL::IoPort::ReadPort8(0x61); /* Enable PIT Channel 2 and disable the PC Speaker */ HL::IoPort::WritePort8(0x61, (Port61State & ~0x02) | 0x01); /* Configure PIT Channel 2 for Read/Write LSB then MSB, Mode 0 */ HL::IoPort::WritePort8(PIT_COMMAND_PORT, 0xB0); /* Initialize the PIT counter with the maximum possible value */ HL::IoPort::WritePort8(PIT_DATA_PORT2, 0xFF); HL::IoPort::WritePort8(PIT_DATA_PORT2, 0xFF); /* Latch and read the initial counter value */ HL::IoPort::WritePort8(PIT_COMMAND_PORT, 0x80); PreviousCount = HL::IoPort::ReadPort8(PIT_DATA_PORT2); PreviousCount |= (HL::IoPort::ReadPort8(PIT_DATA_PORT2) << 8); /* Poll the PIT */ while(TickCounter < TargetTicks) { /* Latch the current counter value without stopping the timer */ HL::IoPort::WritePort8(PIT_COMMAND_PORT, 0x80); CurrentCount = HL::IoPort::ReadPort8(PIT_DATA_PORT2); CurrentCount |= (HL::IoPort::ReadPort8(PIT_DATA_PORT2) << 8); /* Calculate elapsed ticks since the last read */ TickCounter += (PreviousCount - CurrentCount) & 0xFFFF; /* Update the tracking variable */ PreviousCount = CurrentCount; } /* Restore the original state of PIT Port */ HL::IoPort::WritePort8(0x61, Port61State); } /** * Stalls the CPU execution for a specified duration (maximum 3 seconds) using the Time Stamp Counter (TSC). * * @param MicroSeconds * Supplies the number of microseconds to stall execution. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Timer::StallExecutionTsc(IN ULONG MicroSeconds) { ULONGLONG StartTick, TargetTicks; /* Validate input parameter */ if(MicroSeconds == 0) { /* Nothing to do */ return; } else if(MicroSeconds > 3000000) { /* Cap execution stall to 3 seconds */ MicroSeconds = 3000000; } /* Calculate target ticks based on calibrated TSC frequency */ TargetTicks = ((ULONGLONG)MicroSeconds * PerformanceFrequency) / 1000000ULL; StartTick = AR::CpuFunctions::ReadTimeStampCounter(); /* Spin until the elapsed ticks reach the target */ while((AR::CpuFunctions::ReadTimeStampCounter() - StartTick) < TargetTicks) { /* Issue a PAUSE instruction to relieve memory bus contention */ AR::CpuFunctions::YieldProcessor(); } } /** * Enables the profile interrupt for the specified profile source. * * @param ProfileSource * Supplies the source of the profile interrupt to start. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Timer::StartProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) { /* Handle only ProfileTime and ProfileXtKernel */ if(ProfileSource != ProfileTime && ProfileSource != ProfileXtKernel) { /* Invalid profile source, do nothing */ return; } /* Set the global software flag to enable profiling */ ProfilingEnabled = TRUE; } /** * Disables the profile interrupt for the specified profile source. * * @param ProfileSource * Supplies the source of the profile interrupt to stop. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HL::Timer::StopProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) { /* Handle only ProfileTime and ProfileXtKernel */ if(ProfileSource != ProfileTime && ProfileSource != ProfileXtKernel) { /* Invalid profile source, do nothing */ return; } /* Clear the global software flag to disable profiling */ ProfilingEnabled = FALSE; } /** * Checks if the specified hardware timer is supported and available on the current system. * * @param TimerType * Supplies the hardware timer type to query. * * @param IsClock * Supplies TRUE if the timer is intended to be used as an interrupt generator (System Clock), * or FALSE if it is intended to be used as a performance counter (Stoper). * * @return This routine returns TRUE if the timer is available and supported, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN HL::Timer::ValidateTimerSupport(IN TIMER_TYPE TimerType, IN BOOLEAN IsClock) { PACPI_TIMER_INFO AcpiTimerInfo; /* Query ACPI timer info */ HL::Acpi::GetAcpiTimerInfo(&AcpiTimerInfo); /* Validate timer type */ switch(TimerType) { case TimerTsc: /* Check if TSC and RDTSCP are supported */ return (TimerCapabilities.InvariantTsc && TimerCapabilities.RDTSCP) ? TRUE : FALSE; case TimerHpet: /* Check if HPET is supported */ return (HpetAddress != NULLPTR) ? TRUE : FALSE; case TimerAcpiPm: /* Check if ACPI PM Timer is supported */ return (!IsClock && AcpiTimerInfo->TimerPort != 0) ? TRUE : FALSE; case TimerLapic: /* Check if LAPIC Timer (ARAT) is supported */ return (IsClock && TimerCapabilities.Arat) ? TRUE : FALSE; case TimerPit: /* PIT Timer is always supported */ return TRUE; default: /* Invalid timer type, return FALSE */ return FALSE; } } ================================================ FILE: xtoskrnl/includes/ar/amd64/asmsup.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ar/amd64/asmsup.hh * DESCRIPTION: Architecture-specific assembler prototypes * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_AR_ASMSUP_HH #define __XTOSKRNL_AR_ASMSUP_HH #include /* TrampolineEnableXpa end address to calculate trampoline size */ XTCLINK PVOID ArEnableExtendedPhysicalAddressingEnd[]; /* External array of pointers to the interrupt handlers */ XTCLINK ULONG_PTR ArInterruptEntry[256]; /* TrampolineApStartup end address to calculate trampoline size */ XTCLINK PVOID ArStartApplicationProcessorEnd[]; /* External array of pointers to the trap handlers */ XTCLINK ULONG_PTR ArTrapEntry[256]; /* Forward reference for assembler code */ XTCLINK XTCDECL VOID ArEnableExtendedPhysicalAddressing(IN ULONG_PTR PageMap); XTCLINK XTCDECL VOID ArHandleSpuriousInterrupt(VOID); XTCLINK XTCDECL VOID ArStartApplicationProcessor(VOID); #endif /* __XTOSKRNL_AR_ASMSUP_HH */ ================================================ FILE: xtoskrnl/includes/ar/amd64/cpufunc.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ar/amd64/cpufunc.hh * DESCRIPTION: Architecture-specific CPU control and utility functions for low-level system operations * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_AR_CPUFUNC_HH #define __XTOSKRNL_AR_CPUFUNC_HH #include /* Architecture-specific Library */ namespace AR { class CpuFunctions { public: STATIC XTCDECL VOID ClearInterruptFlag(VOID); STATIC XTCDECL BOOLEAN CpuId(IN OUT PCPUID_REGISTERS Registers); STATIC XTCDECL VOID FlushTlb(VOID); STATIC XTCDECL ULONG GetCpuFlags(VOID); STATIC XTASSEMBLY XTCDECL ULONG_PTR GetStackPointer(VOID); STATIC XTCDECL VOID Halt(VOID); STATIC XTCDECL BOOLEAN InterruptsEnabled(VOID); STATIC XTCDECL VOID InvalidateTlbEntry(IN PVOID Address); STATIC XTCDECL VOID LoadGlobalDescriptorTable(IN PVOID Source); STATIC XTCDECL VOID LoadInterruptDescriptorTable(IN PVOID Source); STATIC XTCDECL VOID LoadLocalDescriptorTable(IN USHORT Source); STATIC XTCDECL VOID LoadMxcsrRegister(IN ULONG Source); STATIC XTCDECL VOID LoadSegment(IN USHORT Segment, IN ULONG Source); STATIC XTCDECL VOID LoadTaskRegister(USHORT Source); STATIC XTCDECL VOID MemoryBarrier(VOID); STATIC XTCDECL ULONG_PTR ReadControlRegister(IN USHORT ControlRegister); STATIC XTCDECL ULONG_PTR ReadDebugRegister(IN USHORT DebugRegister); STATIC XTCDECL ULONGLONG ReadGSQuadWord(ULONG Offset); STATIC XTCDECL ULONGLONG ReadModelSpecificRegister(IN ULONG Register); STATIC XTCDECL UINT ReadMxCsrRegister(VOID); STATIC XTCDECL ULONGLONG ReadTimeStampCounter(VOID); STATIC XTCDECL ULONGLONG ReadTimeStampCounterProcessor(OUT PULONG TscAux); STATIC XTCDECL VOID ReadWriteBarrier(VOID); STATIC XTCDECL VOID SetInterruptFlag(VOID); STATIC XTCDECL VOID StoreGlobalDescriptorTable(OUT PVOID Destination); STATIC XTCDECL VOID StoreInterruptDescriptorTable(OUT PVOID Destination); STATIC XTCDECL VOID StoreLocalDescriptorTable(OUT PVOID Destination); STATIC XTCDECL VOID StoreSegment(IN USHORT Segment, OUT PVOID Destination); STATIC XTCDECL VOID StoreTaskRegister(OUT PVOID Destination); STATIC XTCDECL VOID WriteControlRegister(IN USHORT ControlRegister, IN UINT_PTR Value); STATIC XTCDECL VOID WriteDebugRegister(IN USHORT DebugRegister, IN UINT_PTR Value); STATIC XTCDECL VOID WriteEflagsRegister(IN UINT_PTR Value); STATIC XTCDECL VOID WriteModelSpecificRegister(IN ULONG Register, IN ULONGLONG Value); STATIC XTCDECL VOID YieldProcessor(VOID); }; } #endif /* __XTOSKRNL_AR_CPUFUNC_HH */ ================================================ FILE: xtoskrnl/includes/ar/amd64/procsup.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ar/amd64/procsup.hh * DESCRIPTION: Architecture-specific routines for AMD64 processor initialization and system structure setup * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_AR_PROCSUP_HH #define __XTOSKRNL_AR_PROCSUP_HH #include /* Architecture-specific Library */ namespace AR { class ProcessorSupport { private: STATIC UCHAR BootStack[KERNEL_STACK_SIZE]; STATIC UCHAR FaultStack[KERNEL_STACK_SIZE]; STATIC KGDTENTRY InitialGdt[GDT_ENTRIES]; STATIC KIDTENTRY InitialIdt[IDT_ENTRIES]; STATIC KPROCESSOR_BLOCK InitialProcessorBlock; STATIC KTSS InitialTss; STATIC UCHAR NmiStack[KERNEL_STACK_SIZE]; public: STATIC XTAPI PVOID GetBootStack(VOID); STATIC XTAPI VOID GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType, OUT PVOID *TrampolineCode, OUT PULONG_PTR TrampolineSize); STATIC XTAPI VOID InitializeProcessor(IN PVOID ProcessorStructures); STATIC XTAPI VOID InitializeProcessorStructures(IN PVOID ProcessorStructures, OUT PKGDTENTRY *Gdt, OUT PKTSS *Tss, OUT PKPROCESSOR_BLOCK *ProcessorBlock, OUT PVOID *KernelBootStack, OUT PVOID *KernelFaultStack, OUT PVOID *KernelNmiStack); STATIC XTAPI VOID SetIdtGate(IN PKIDTENTRY Idt, IN USHORT Vector, IN PVOID Handler, IN USHORT Selector, IN USHORT Ist, IN USHORT Dpl, IN USHORT Type); private: STATIC XTAPI VOID IdentifyProcessor(VOID); STATIC XTAPI VOID IdentifyProcessorFeatures(VOID); STATIC XTAPI VOID InitializeGdt(IN PKPROCESSOR_BLOCK ProcessorBlock); STATIC XTAPI VOID InitializeIdt(IN PKPROCESSOR_BLOCK ProcessorBlock); STATIC XTAPI VOID InitializeProcessorBlock(OUT PKPROCESSOR_BLOCK ProcessorBlock, IN PKGDTENTRY Gdt, IN PKIDTENTRY Idt, IN PKTSS Tss, IN PVOID DpcStack); STATIC XTAPI VOID InitializeProcessorRegisters(VOID); STATIC XTAPI VOID InitializeSegments(VOID); STATIC XTAPI VOID InitializeTss(IN PKPROCESSOR_BLOCK ProcessorBlock, IN PVOID KernelBootStack, IN PVOID KernelFaultStack, IN PVOID KernelNmiStack); STATIC XTAPI VOID SetGdtEntry(IN PKGDTENTRY Gdt, IN USHORT Selector, IN ULONG_PTR Base, IN ULONG Limit, IN UCHAR Type, IN UCHAR Dpl, IN UCHAR SegmentMode); STATIC XTAPI VOID SetGdtEntryBase(IN PKGDTENTRY Gdt, IN USHORT Selector, IN ULONG_PTR Base); }; } #endif /* __XTOSKRNL_AR_PROCSUP_HH */ ================================================ FILE: xtoskrnl/includes/ar/amd64/traps.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ar/amd64/traps.hh * DESCRIPTION: Trap handling routines and the dispatcher for processor exceptions * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_AR_TRAPS_HH #define __XTOSKRNL_AR_TRAPS_HH #include /* Architecture-specific Library */ namespace AR { class Traps { private: STATIC PINTERRUPT_HANDLER UnhandledInterruptRoutine; public: STATIC XTCDECL VOID DispatchInterrupt(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("ArDispatchInterrupt"); STATIC XTCDECL VOID DispatchTrap(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("ArDispatchTrap"); STATIC XTCDECL VOID InitializeSystemCallMsrs(VOID); STATIC XTCDECL VOID SetUnhandledInterruptRoutine(PINTERRUPT_HANDLER Handler); private: STATIC XTCDECL VOID HandleSystemCall32(VOID); STATIC XTCDECL VOID HandleSystemCall64(VOID); STATIC XTCDECL VOID HandleTrap00(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap01(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap02(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap03(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap04(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap05(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap06(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap07(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap08(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap09(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap0A(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap0B(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap0C(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap0D(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap0E(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap10(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap11(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap12(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap13(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap1F(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap2C(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap2D(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap2F(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrapE1(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrapFF(IN PKTRAP_FRAME TrapFrame); }; } #endif /* __XTOSKRNL_AR_TRAPS_HH */ ================================================ FILE: xtoskrnl/includes/ar/i686/asmsup.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ar/i686/asmsup.hh * DESCRIPTION: Architecture-specific assembler prototypes * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_AR_ASMSUP_HH #define __XTOSKRNL_AR_ASMSUP_HH #include /* TrampolineEnableXpa end address to calculate trampoline size */ XTCLINK PVOID ArEnableExtendedPhysicalAddressingEnd[]; /* External array of pointers to the interrupt handlers */ XTCLINK ULONG_PTR ArInterruptEntry[256]; /* TrampolineApStartup end address to calculate trampoline size */ XTCLINK PVOID ArStartApplicationProcessorEnd[]; /* External array of pointers to the trap handlers */ XTCLINK ULONG_PTR ArTrapEntry[256]; /* Forward reference for assembler code */ XTCLINK XTCDECL VOID ArEnableExtendedPhysicalAddressing(IN ULONG_PTR PageMap); XTCLINK XTCDECL VOID ArHandleSpuriousInterrupt(VOID); XTCLINK XTCDECL VOID ArStartApplicationProcessor(VOID); #endif /* __XTOSKRNL_AR_ASMSUP_HH */ ================================================ FILE: xtoskrnl/includes/ar/i686/cpufunc.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ar/i686/cpufunc.hh * DESCRIPTION: Architecture-specific CPU control and utility functions for low-level system operations * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_AR_CPUFUNC_HH #define __XTOSKRNL_AR_CPUFUNC_HH #include /* Architecture-specific Library */ namespace AR { class CpuFunctions { public: STATIC XTCDECL VOID ClearInterruptFlag(VOID); STATIC XTCDECL BOOLEAN CpuId(IN OUT PCPUID_REGISTERS Registers); STATIC XTCDECL VOID FlushTlb(VOID); STATIC XTCDECL ULONG GetCpuFlags(VOID); STATIC XTASSEMBLY XTCDECL ULONG_PTR GetStackPointer(VOID); STATIC XTCDECL VOID Halt(VOID); STATIC XTCDECL BOOLEAN InterruptsEnabled(VOID); STATIC XTCDECL VOID InvalidateTlbEntry(IN PVOID Address); STATIC XTCDECL VOID LoadGlobalDescriptorTable(IN PVOID Source); STATIC XTCDECL VOID LoadInterruptDescriptorTable(IN PVOID Source); STATIC XTCDECL VOID LoadLocalDescriptorTable(IN USHORT Source); STATIC XTCDECL VOID LoadSegment(IN USHORT Segment, IN ULONG Source); STATIC XTCDECL VOID LoadTaskRegister(USHORT Source); STATIC XTCDECL VOID MemoryBarrier(VOID); STATIC XTCDECL ULONG_PTR ReadControlRegister(IN USHORT ControlRegister); STATIC XTCDECL ULONG_PTR ReadDebugRegister(IN USHORT DebugRegister); STATIC XTCDECL ULONG ReadFSDualWord(ULONG Offset); STATIC XTCDECL ULONGLONG ReadModelSpecificRegister(IN ULONG Register); STATIC XTCDECL UINT ReadMxCsrRegister(VOID); STATIC XTCDECL ULONGLONG ReadTimeStampCounter(VOID); STATIC XTCDECL ULONGLONG ReadTimeStampCounterProcessor(OUT PULONG TscAux); STATIC XTCDECL VOID ReadWriteBarrier(VOID); STATIC XTCDECL VOID SetInterruptFlag(VOID); STATIC XTCDECL VOID StoreGlobalDescriptorTable(OUT PVOID Destination); STATIC XTCDECL VOID StoreInterruptDescriptorTable(OUT PVOID Destination); STATIC XTCDECL VOID StoreLocalDescriptorTable(OUT PVOID Destination); STATIC XTCDECL VOID StoreSegment(IN USHORT Segment, OUT PVOID Destination); STATIC XTCDECL VOID StoreTaskRegister(OUT PVOID Destination); STATIC XTCDECL VOID WriteControlRegister(IN USHORT ControlRegister, IN UINT_PTR Value); STATIC XTCDECL VOID WriteDebugRegister(IN USHORT DebugRegister, IN UINT_PTR Value); STATIC XTCDECL VOID WriteEflagsRegister(IN UINT_PTR Value); STATIC XTCDECL VOID WriteModelSpecificRegister(IN ULONG Register, IN ULONGLONG Value); STATIC XTCDECL VOID YieldProcessor(VOID); }; } #endif /* __XTOSKRNL_AR_CPUFUNC_HH */ ================================================ FILE: xtoskrnl/includes/ar/i686/procsup.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ar/i686/procsup.hh * DESCRIPTION: Architecture-specific routines for i686 processor initialization and system structure setup * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_AR_PROCSUP_HH #define __XTOSKRNL_AR_PROCSUP_HH #include /* Architecture-specific Library */ namespace AR { class ProcessorSupport { private: STATIC UCHAR BootStack[KERNEL_STACK_SIZE]; STATIC UCHAR DoubleFaultTss[KTSS_IO_MAPS]; STATIC UCHAR FaultStack[KERNEL_STACK_SIZE]; STATIC KGDTENTRY InitialGdt[GDT_ENTRIES]; STATIC KIDTENTRY InitialIdt[IDT_ENTRIES]; STATIC KPROCESSOR_BLOCK InitialProcessorBlock; STATIC KTSS InitialTss; STATIC UCHAR NmiStack[KERNEL_STACK_SIZE]; STATIC UCHAR NonMaskableInterruptTss[KTSS_IO_MAPS]; public: STATIC XTAPI PVOID GetBootStack(VOID); STATIC XTAPI VOID GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType, OUT PVOID *TrampolineCode, OUT PULONG_PTR TrampolineSize); STATIC XTAPI VOID InitializeProcessor(IN PVOID ProcessorStructures); STATIC XTAPI VOID InitializeProcessorStructures(IN PVOID ProcessorStructures, OUT PKGDTENTRY *Gdt, OUT PKTSS *Tss, OUT PKPROCESSOR_BLOCK *ProcessorBlock, OUT PVOID *KernelBootStack, OUT PVOID *KernelFaultStack, OUT PVOID *KernelNmiStack); STATIC XTAPI VOID SetIdtGate(IN PKIDTENTRY Idt, IN USHORT Vector, IN PVOID Handler, IN USHORT Selector, IN USHORT Ist, IN USHORT Dpl, IN USHORT Type); private: STATIC XTAPI VOID IdentifyProcessor(VOID); STATIC XTAPI VOID IdentifyProcessorFeatures(VOID); STATIC XTAPI VOID InitializeGdt(IN PKPROCESSOR_BLOCK ProcessorBlock); STATIC XTAPI VOID InitializeIdt(IN PKPROCESSOR_BLOCK ProcessorBlock); STATIC XTAPI VOID InitializeProcessorBlock(OUT PKPROCESSOR_BLOCK ProcessorBlock, IN PKGDTENTRY Gdt, IN PKIDTENTRY Idt, IN PKTSS Tss, IN PVOID DpcStack); STATIC XTAPI VOID InitializeProcessorRegisters(VOID); STATIC XTAPI VOID InitializeSegments(VOID); STATIC XTAPI VOID InitializeTss(IN PKPROCESSOR_BLOCK ProcessorBlock, IN PVOID KernelBootStack, IN PVOID KernelFaultStack, IN PVOID KernelNmiStack); STATIC XTAPI VOID SetDoubleFaultTssEntry(IN PKPROCESSOR_BLOCK ProcessorBlock, IN PVOID KernelFaultStack); STATIC XTAPI VOID SetGdtEntry(IN PKGDTENTRY Gdt, IN USHORT Selector, IN ULONG_PTR Base, IN ULONG Limit, IN UCHAR Type, IN UCHAR Dpl, IN UCHAR SegmentMode); STATIC XTAPI VOID SetGdtEntryBase(IN PKGDTENTRY Gdt, IN USHORT Selector, IN ULONG_PTR Base); STATIC XTAPI VOID SetNonMaskableInterruptTssEntry(IN PKPROCESSOR_BLOCK ProcessorBlock, IN PVOID KernelNmiStack); }; } #endif /* __XTOSKRNL_AR_PROCSUP_HH */ ================================================ FILE: xtoskrnl/includes/ar/i686/traps.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ar/i686/traps.hh * DESCRIPTION: Trap handling routines and the dispatcher for processor exceptions * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_AR_TRAPS_HH #define __XTOSKRNL_AR_TRAPS_HH #include /* Architecture-specific Library */ namespace AR { class Traps { private: STATIC PINTERRUPT_HANDLER UnhandledInterruptRoutine; public: STATIC XTCDECL VOID DispatchInterrupt(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("_ArDispatchInterrupt"); STATIC XTCDECL VOID DispatchTrap(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("_ArDispatchTrap"); STATIC XTCDECL VOID SetUnhandledInterruptRoutine(PINTERRUPT_HANDLER Handler); private: STATIC XTCDECL VOID HandleTrap00(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap01(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap02(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap03(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap04(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap05(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap06(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap07(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap08(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap09(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap0A(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap0B(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap0C(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap0D(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap0E(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap10(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap11(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap12(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap13(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap2A(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap2B(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap2C(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap2D(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap2E(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrapFF(IN PKTRAP_FRAME TrapFrame); }; } #endif /* __XTOSKRNL_AR_TRAPS_HH */ ================================================ FILE: xtoskrnl/includes/ar.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ar.hh * DESCRIPTION: Architecture Library * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_AR_HH #define __XTOSKRNL_AR_HH #include #include XTOS_ARCH_HEADER(ar, asmsup.hh) #include XTOS_ARCH_HEADER(ar, cpufunc.hh) #include XTOS_ARCH_HEADER(ar, procsup.hh) #include XTOS_ARCH_HEADER(ar, traps.hh) #endif /* __XTOSKRNL_AR_HH */ ================================================ FILE: xtoskrnl/includes/ex/rundown.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ex/rundown.hh * DESCRIPTION: Rundown protection mechanism * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_EX_RUNDOWN_HH #define __XTOSKRNL_EX_RUNDOWN_HH #include /* Architecture-specific Library */ namespace EX { class Rundown { public: STATIC XTFASTCALL BOOLEAN AcquireProtection(IN PEX_RUNDOWN_REFERENCE Descriptor); STATIC XTFASTCALL VOID CompleteProtection(IN PEX_RUNDOWN_REFERENCE Descriptor); STATIC XTFASTCALL VOID InitializeProtection(IN PEX_RUNDOWN_REFERENCE Descriptor); STATIC XTFASTCALL VOID ReInitializeProtection(IN PEX_RUNDOWN_REFERENCE Descriptor); STATIC XTFASTCALL VOID ReleaseProtection(IN PEX_RUNDOWN_REFERENCE Descriptor); STATIC XTFASTCALL VOID WaitForProtectionRelease(IN PEX_RUNDOWN_REFERENCE Descriptor); }; } #endif /* __XTOSKRNL_EX_RUNDOWN_HH */ ================================================ FILE: xtoskrnl/includes/ex.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ex.hh * DESCRIPTION: Kernel Executive * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_EX_HH #define __XTOSKRNL_EX_HH #include #include #endif /* __XTOSKRNL_EX_HH */ ================================================ FILE: xtoskrnl/includes/hl/acpi.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl/acpi.hh * DESCRIPTION: Advanced Configuration and Power Interface (ACPI) support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_ACPI_HH #define __XTOSKRNL_HL_ACPI_HH #include /* Hardware Layer */ namespace HL { class Acpi { private: STATIC ULONG CacheCount; STATIC ACPI_CACHE_LIST CacheEntries[ACPI_MAX_CACHED_TABLES]; STATIC LIST_ENTRY CacheList; STATIC PACPI_RSDP RsdpStructure; STATIC ACPI_SYSTEM_INFO SystemInfo; STATIC ACPI_TIMER_INFO TimerInfo; public: STATIC XTAPI XTSTATUS GetAcpiSystemDescriptionPointer(OUT PACPI_RSDP *Rsdp); STATIC XTAPI XTSTATUS GetAcpiTable(IN ULONG Signature, OUT PACPI_DESCRIPTION_HEADER *AcpiTable); STATIC XTAPI VOID GetAcpiTimerInfo(OUT PACPI_TIMER_INFO *AcpiTimerInfo); STATIC XTAPI VOID GetSystemInformation(OUT PACPI_SYSTEM_INFO *SystemInfo); STATIC XTAPI XTSTATUS InitializeAcpi(VOID); STATIC XTAPI XTSTATUS InitializeAcpiSystemInformation(VOID); private: STATIC XTAPI VOID CacheAcpiTable(IN PACPI_DESCRIPTION_HEADER AcpiTable); STATIC XTAPI XTSTATUS InitializeAcpiCache(VOID); STATIC XTAPI XTSTATUS InitializeAcpiSystemDescriptionTable(OUT PACPI_DESCRIPTION_HEADER *AcpiTable); STATIC XTAPI XTSTATUS InitializeAcpiSystemStructure(VOID); STATIC XTAPI XTSTATUS InitializeAcpiTimer(VOID); STATIC XTAPI XTSTATUS QueryAcpiCache(IN ULONG Signature, OUT PACPI_DESCRIPTION_HEADER *AcpiTable); STATIC XTAPI XTSTATUS QueryAcpiTables(IN ULONG Signature, OUT PACPI_DESCRIPTION_HEADER *AcpiTable); STATIC XTAPI BOOLEAN ValidateAcpiTable(IN PVOID Buffer, IN UINT_PTR Size); }; } #endif /* __XTOSKRNL_HL_ACPI_HH */ ================================================ FILE: xtoskrnl/includes/hl/cport.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl/cpu.hh * DESCRIPTION: Serial (COM) port support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_CPORT_HH #define __XTOSKRNL_HL_CPORT_HH #include /* Hardware Layer */ namespace HL { class ComPort { public: STATIC XTCDECL XTSTATUS ReadComPort(IN PCPPORT Port, OUT PUCHAR Byte, IN BOOLEAN Wait, IN BOOLEAN Poll); STATIC XTCDECL UCHAR ReadComPortLsr(IN PCPPORT Port, IN UCHAR Byte); STATIC XTCDECL XTSTATUS InitializeComPort(IN OUT PCPPORT Port, IN PUCHAR PortAddress, IN ULONG BaudRate); STATIC XTCDECL XTSTATUS WriteComPort(IN PCPPORT Port, IN UCHAR Byte); }; } #endif /* __XTOSKRNL_HL_CPORT_HH */ ================================================ FILE: xtoskrnl/includes/hl/cpu.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl/cpu.hh * DESCRIPTION: HAL processor support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_CPU_HH #define __XTOSKRNL_HL_CPU_HH #include /* Hardware Layer */ namespace HL { class Cpu { private: STATIC KAFFINITY ActiveProcessors; public: STATIC XTAPI VOID InitializeProcessor(VOID); STATIC XTAPI XTSTATUS StartAllProcessors(VOID); }; } #endif /* __XTOSKRNL_HL_CPU_HH */ ================================================ FILE: xtoskrnl/includes/hl/fbdev.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl/fbdev.hh * DESCRIPTION: FrameBuffer support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_FBDEV_HH #define __XTOSKRNL_HL_FBDEV_HH #include /* Hardware Layer */ namespace HL { class FrameBuffer { private: STATIC HL_FRAMEBUFFER_DATA FrameBufferData; STATIC PVOID ScreenShadowBuffer; STATIC HL_SCROLL_REGION_DATA ScrollRegionData; public: STATIC XTAPI VOID ClearScreen(IN ULONG Color); STATIC XTCDECL XTSTATUS DisplayCharacter(IN WCHAR Character); STATIC XTAPI XTSTATUS EnableShadowBuffer(VOID); STATIC XTAPI VOID GetFrameBufferResolution(OUT PULONG Width, OUT PULONG Height); STATIC XTAPI XTSTATUS InitializeFrameBuffer(VOID); STATIC XTAPI VOID InitializeScrollRegion(IN ULONG Left, IN ULONG Top, IN ULONG Right, IN ULONG Bottom, IN ULONG FontColor); STATIC XTAPI VOID UpdateScreen(VOID); STATIC XTAPI VOID UpdateScreenRegion(IN ULONG Left, IN ULONG Top, IN ULONG Right, IN ULONG Bottom); private: STATIC XTAPI VOID DrawCharacter(IN ULONG PositionX, IN ULONG PositionY, IN ULONG Color, IN WCHAR WideCharacter); STATIC XTAPI VOID DrawPixel(IN ULONG PositionX, IN ULONG PositionY, IN ULONG Color); STATIC XTAPI ULONG GetRGBColor(IN ULONG Color); STATIC XTAPI VOID ScrollRegion(VOID); }; } #endif /* __XTOSKRNL_HL_FBDEV_HH */ ================================================ FILE: xtoskrnl/includes/hl/firmware.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl/firmware.hh * DESCRIPTION: UEFI/BIOS Firmware support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_FIRMWARE_HH #define __XTOSKRNL_HL_FIRMWARE_HH #include /* Hardware Layer */ namespace HL { class Firmware { public: STATIC XTFASTCALL UCHAR ReadCmosRegister(IN UCHAR Register); STATIC XTFASTCALL VOID WriteCmosRegister(IN UCHAR Register, IN UCHAR Value); }; } #endif /* __XTOSKRNL_HL_FIRMWARE_HH */ ================================================ FILE: xtoskrnl/includes/hl/init.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl/init.hh * DESCRIPTION: Hardware layer initialization * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_INIT_HH #define __XTOSKRNL_HL_INIT_HH #include /* Hardware Layer */ namespace HL { class Init { public: STATIC XTAPI XTSTATUS InitializeSystem(VOID); }; } #endif /* __XTOSKRNL_HL_INIT_HH */ ================================================ FILE: xtoskrnl/includes/hl/ioport.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl/ioport.hh * DESCRIPTION: I/O port access routines * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_IOPORT_HH #define __XTOSKRNL_HL_IOPORT_HH #include /* Hardware Layer */ namespace HL { class IoPort { public: STATIC XTCDECL UCHAR ReadPort8(IN USHORT Port); STATIC XTCDECL USHORT ReadPort16(IN USHORT Port); STATIC XTCDECL ULONG ReadPort32(IN USHORT Port); STATIC XTCDECL VOID WritePort8(IN USHORT Port, IN UCHAR Value); STATIC XTCDECL VOID WritePort16(IN USHORT Port, IN USHORT Value); STATIC XTCDECL VOID WritePort32(IN USHORT Port, IN ULONG Value); }; } #endif /* __XTOSKRNL_HL_IOPORT_HH */ ================================================ FILE: xtoskrnl/includes/hl/ioreg.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl/ioreg.hh * DESCRIPTION: Basic I/O registers access functionality * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_IOREG_HH #define __XTOSKRNL_HL_IOREG_HH #include /* Hardware Layer */ namespace HL { class IoRegister { public: STATIC XTAPI UCHAR ReadRegister8(IN PVOID Register); STATIC XTAPI USHORT ReadRegister16(IN PVOID Register); STATIC XTAPI ULONG ReadRegister32(IN PVOID Register); STATIC XTAPI VOID WriteRegister8(IN PVOID Register, IN UCHAR Value); STATIC XTAPI VOID WriteRegister16(IN PVOID Register, IN USHORT Value); STATIC XTAPI VOID WriteRegister32(IN PVOID Register, IN ULONG Value); }; } #endif /* __XTOSKRNL_HL_IOREG_HH */ ================================================ FILE: xtoskrnl/includes/hl/irq.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl/irq.hh * DESCRIPTION: Interrupts support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_IRQ_HH #define __XTOSKRNL_HL_IRQ_HH #include /* Hardware Layer */ namespace HL { class Irq { public: STATIC XTAPI VOID BeginSystemInterrupt(IN KRUNLEVEL RunLevel, OUT PKRUNLEVEL OldRunLevel); STATIC XTAPI VOID EndInterrupt(IN PKTRAP_FRAME TrapFrame, IN KRUNLEVEL RunLevel); STATIC XTAPI VOID EndSystemInterrupt(IN PKTRAP_FRAME TrapFrame, IN KRUNLEVEL RunLevel); STATIC XTCDECL VOID HandleProfileInterrupt(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleUnexpectedInterrupt(IN PKTRAP_FRAME TrapFrame); STATIC XTAPI PVOID QueryInterruptHandler(IN ULONG Vector); STATIC XTAPI PVOID QuerySystemInterruptHandler(IN ULONG Vector); STATIC XTAPI VOID RegisterInterruptHandler(IN ULONG Vector, IN PVOID Handler); STATIC XTAPI VOID RegisterSystemInterruptHandler(IN ULONG Vector, IN PINTERRUPT_HANDLER Handler); STATIC XTFASTCALL VOID SendSoftwareInterrupt(IN KRUNLEVEL RunLevel); }; } #endif /* __XTOSKRNL_HL_IRQ_HH */ ================================================ FILE: xtoskrnl/includes/hl/pic.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl/pic.hh * DESCRIPTION: HAL processor support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_PIC_HH #define __XTOSKRNL_HL_PIC_HH #include /* Hardware Layer */ namespace HL { class Pic { private: STATIC APIC_MODE ApicMode; STATIC ULONG ControllerCount; STATIC IOAPIC_DATA Controllers[IOAPIC_MAX_CONTROLLERS]; STATIC ULONG IrqOverrideCount; STATIC ACPI_MADT_INTERRUPT_OVERRIDE IrqOverrides[IOAPIC_MAX_OVERRIDES]; STATIC UCHAR MappedVectors[256]; public: STATIC XTAPI VOID AllocateSystemInterrupt(IN UCHAR Irq, IN UCHAR RunLevel, IN UCHAR Vector); STATIC XTAPI VOID ClearApicErrors(VOID); STATIC XTAPI ULONG GetCpuApicId(VOID); STATIC XTAPI VOID InitializeIOApic(VOID); STATIC XTAPI VOID InitializePic(VOID); STATIC XTFASTCALL ULONGLONG ReadApicRegister(IN APIC_REGISTER Register); STATIC XTAPI VOID SendBroadcastIpi(IN ULONG Vector, IN BOOLEAN Self); STATIC XTAPI VOID SendEoi(VOID); STATIC XTAPI VOID SendIpi(IN ULONG ApicId, IN ULONG Vector, IN APIC_DM DeliveryMode, IN APIC_DSH Destination, IN ULONG TriggerMode); STATIC XTAPI VOID SendSelfIpi(IN ULONG Vector); STATIC XTFASTCALL VOID WriteApicRegister(IN APIC_REGISTER Register, IN ULONGLONG Value); private: STATIC XTAPI BOOLEAN CheckApicSupport(VOID); STATIC XTAPI BOOLEAN CheckX2ApicSupport(VOID); STATIC XTAPI XTSTATUS DetectIoApicControllers(VOID); STATIC XTAPI VOID ResolveInterruptOverride(IN UCHAR Irq, OUT PULONG Gsi, OUT PUSHORT Flags); STATIC XTAPI XTSTATUS GetIoApicController(IN ULONG Gsi, OUT PIOAPIC_DATA *Controller, OUT PULONG EntryNumber); STATIC XTCDECL VOID HandleApicErrorInterrupt(IN PKTRAP_FRAME TrapFrame); STATIC XTAPI VOID InitializeApic(VOID); STATIC XTAPI VOID InitializeLegacyPic(VOID); STATIC XTFASTCALL ULONG ReadIOApicRegister(IN PIOAPIC_DATA Controller, IN UCHAR Register); STATIC XTFASTCALL IOAPIC_REDIRECTION_REGISTER ReadRedirectionEntry(IN PIOAPIC_DATA Controller, IN ULONG EntryNumber); STATIC XTFASTCALL UCHAR TranslateGsiToVector(IN ULONG Gsi); STATIC XTFASTCALL VOID WriteIOApicRegister(IN PIOAPIC_DATA Controller, IN UCHAR Register, IN ULONG DataValue); STATIC XTFASTCALL VOID WriteRedirectionEntry(IN PIOAPIC_DATA Controller, IN ULONG EntryNumber, IN IOAPIC_REDIRECTION_REGISTER EntryData); }; } #endif /* __XTOSKRNL_HL_PIC_HH */ ================================================ FILE: xtoskrnl/includes/hl/rtc.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl/rtc.hh * DESCRIPTION: Hardware Real-Time Clock (RTC) support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_RTC_HH #define __XTOSKRNL_HL_RTC_HH #include /* Hardware Layer */ namespace HL { class Rtc { public: STATIC XTAPI XTSTATUS GetRealTimeClock(OUT PTIME_FIELDS Time); STATIC XTAPI XTSTATUS SetRealTimeClock(IN PTIME_FIELDS Time); }; } #endif /* __XTOSKRNL_HL_RTC_HH */ ================================================ FILE: xtoskrnl/includes/hl/runlevel.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl/runlevel.hh * DESCRIPTION: Run Level management support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_RUNLEVEL_HH #define __XTOSKRNL_HL_RUNLEVEL_HH #include /* Hardware Layer */ namespace HL { class RunLevel { public: STATIC XTFASTCALL KRUNLEVEL GetRunLevel(VOID); STATIC XTFASTCALL VOID SetRunLevel(IN KRUNLEVEL RunLevel); STATIC XTFASTCALL UCHAR TransformRunLevelToSoftwareVector(IN KRUNLEVEL RunLevel); private: STATIC XTFASTCALL KRUNLEVEL TransformApicTprToRunLevel(IN UCHAR Tpr); STATIC XTFASTCALL UCHAR TransformRunLevelToApicTpr(IN KRUNLEVEL RunLevel); }; } #endif /* __XTOSKRNL_HL_RUNLEVEL_HH */ ================================================ FILE: xtoskrnl/includes/hl/timer.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl/timer.hh * DESCRIPTION: ACPI Timer support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_TIMER_HH #define __XTOSKRNL_HL_TIMER_HH #include /* Hardware Layer */ namespace HL { class Timer { private: STATIC ULONG AcpiPmPerformanceCounter; STATIC TIMER_TYPE ClockType; STATIC ULONG FractionalIncrement; STATIC PVOID HpetAddress; STATIC ULONGLONG HpetFrequency; STATIC KSPIN_LOCK PerformanceCounterLock; STATIC ULONGLONG PerformanceFrequency; STATIC ULONGLONG PitPerformanceCounter; STATIC ULONG PitRollover; STATIC BOOLEAN ProfilingEnabled; STATIC ULONG ProfilingTicks; STATIC ULONG RunningFraction; STATIC ULONGLONG SystemPerformanceCounter; STATIC ULONG TimeIncrement; STATIC TIMER_CAPABILITIES TimerCapabilities; STATIC ULONG TimerFrequency; STATIC TIMER_ROUTINES TimerRoutines; STATIC TIMER_TYPE TimerType; public: STATIC XTAPI VOID InitializeTimer(VOID); STATIC XTAPI LARGE_INTEGER QueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceFrequency); STATIC XTAPI ULONG SetClockRate(IN ULONG Rate); STATIC XTAPI ULONG_PTR SetProfileInterval(IN ULONG_PTR Interval); STATIC XTAPI VOID StallExecution(IN ULONG MicroSeconds); STATIC XTAPI VOID StartProfileInterrupt(IN KPROFILE_SOURCE ProfileSource); STATIC XTAPI VOID StopProfileInterrupt(IN KPROFILE_SOURCE ProfileSource); private: STATIC XTAPI XTSTATUS CalibrateApicTimer(); STATIC XTAPI ULONGLONG CalibrateTscCounter(VOID); STATIC XTAPI VOID ConfigureTimeIncrement(IN ULONGLONG BaseFrequency, IN ULONGLONG HardwareDivider); STATIC XTAPI XTSTATUS DetectHpet(VOID); STATIC XTCDECL VOID HandleClockInterrupt(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleClockIpiInterrupt(IN PKTRAP_FRAME TrapFrame); STATIC XTAPI XTSTATUS InitializeApicTimer(VOID); STATIC XTAPI XTSTATUS InitializeHpetTimer(VOID); STATIC XTAPI XTSTATUS InitializePitTimer(VOID); STATIC XTAPI VOID ProbeTimerType(VOID); STATIC XTAPI ULONGLONG QueryPerformanceCounterAcpiPm(VOID); STATIC XTAPI ULONGLONG QueryPerformanceCounterHpet(VOID); STATIC XTAPI ULONGLONG QueryPerformanceCounterPit(VOID); STATIC XTAPI ULONGLONG QueryPerformanceCounterTsc(VOID); STATIC XTAPI VOID QueryTimerCapabilities(VOID); STATIC XTAPI ULONG SetClockRateApic(ULONG TargetIncrement); STATIC XTAPI VOID StallExecutionAcpiPm(IN ULONG MicroSeconds); STATIC XTAPI VOID StallExecutionHpet(IN ULONG MicroSeconds); STATIC XTAPI VOID StallExecutionPit(IN ULONG MicroSeconds); STATIC XTAPI VOID StallExecutionTsc(IN ULONG MicroSeconds); STATIC XTAPI BOOLEAN ValidateTimerSupport(IN TIMER_TYPE TimerType, IN BOOLEAN IsClock); }; } #endif /* __XTOSKRNL_HL_TIMER_HH */ ================================================ FILE: xtoskrnl/includes/hl.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/hl.hh * DESCRIPTION: Hardware Layer * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_HL_HH #define __XTOSKRNL_HL_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif /* __XTOSKRNL_HL_HH */ ================================================ FILE: xtoskrnl/includes/kd/dbg.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/kd/dbg.hh * DESCRIPTION: Kernel debugging support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KD_DBG_HH #define __XTOSKRNL_KD_DBG_HH #include /* Redefine DebugPrint macro for the kernel to enable early debugging */ #undef DebugPrint #ifdef DBG #define DebugPrint(Format, ...) if(KD::DebugIo::KdPrint) KD::DebugIo::KdPrint(Format, __VA_ARGS__); #else #define DebugPrint(Format, ...) ((VOID)NULLPTR) #endif #endif /* __XTOSKRNL_KD_DBG_HH */ ================================================ FILE: xtoskrnl/includes/kd/dbgio.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/kd/dbgio.hh * DESCRIPTION: Kernel Debugger I/O support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KD_DBGIO_HH #define __XTOSKRNL_KD_DBGIO_HH #include /* Kernel Debugger */ namespace KD { class DebugIo { public: STATIC PKD_PRINT_ROUTINE KdPrint; private: STATIC KSPIN_LOCK DebugIoLock; STATIC KD_DEBUG_MODE DebugMode; STATIC PKD_INIT_ROUTINE IoProvidersInitRoutines[KDBG_PROVIDERS_COUNT]; STATIC LIST_ENTRY Providers; STATIC CPPORT SerialPort; STATIC ULONG SerialPortList[COMPORT_COUNT]; public: STATIC XTCDECL VOID DbgPrint(PCWSTR Format, ...); STATIC XTCDECL VOID DbgPrint(PCWSTR Format, VA_LIST Arguments); STATIC XTAPI XTSTATUS InitializeDebugIoProviders(VOID); STATIC XTAPI VOID SetPrintRoutine(PKD_PRINT_ROUTINE DebugPrintRoutine); private: STATIC XTAPI XTSTATUS DetectDebugPorts(VOID); STATIC XTAPI XTSTATUS InitializeFrameBufferProvider(VOID); STATIC XTAPI XTSTATUS InitializeSerialPortProvider(VOID); STATIC XTCDECL XTSTATUS SerialWriteCharacter(WCHAR Character); }; } #endif /* __XTOSKRNL_KD_DBGIO_HH */ ================================================ FILE: xtoskrnl/includes/kd.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/kd.hh * DESCRIPTION: Kernel Debugger * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KD_HH #define __XTOSKRNL_KD_HH #include #include #include #endif /* __XTOSKRNL_KD_HH */ ================================================ FILE: xtoskrnl/includes/ke/apc.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/apc.hh * DESCRIPTION: Kernel APC objects support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_APC_HH #define __XTOSKRNL_KE_APC_HH #include /* Kernel Library */ namespace KE { class Apc { public: STATIC XTAPI VOID InitializeApc(IN PKAPC Apc, IN PKTHREAD Thread, IN KAPC_ENVIRONMENT Environment, IN PKKERNEL_ROUTINE KernelRoutine, IN PKRUNDOWN_ROUTINE RundownRoutine, IN PKNORMAL_ROUTINE NormalRoutine, IN KPROCESSOR_MODE ApcMode, IN PVOID Context); }; } #endif /* __XTOSKRNL_KE_APC_HH */ ================================================ FILE: xtoskrnl/includes/ke/bootinfo.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/bootinfo.hh * DESCRIPTION: Bootloader-provided system information handling support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_BOOTINFO_HH #define __XTOSKRNL_KE_BOOTINFO_HH #include /* Kernel Library */ namespace KE { class BootInformation { private: STATIC PKERNEL_INITIALIZATION_BLOCK InitializationBlock; public: STATIC XTAPI PKD_PRINT_ROUTINE GetDebugPrint(VOID); STATIC XTAPI SYSTEM_FIRMWARE_TYPE GetFirmwareType(VOID); STATIC XTAPI XTSTATUS GetKernelParameter(IN PCWSTR ParameterName, OUT PCWSTR *Parameter); STATIC XTAPI XTSTATUS GetKernelParameterValue(IN PCWSTR ParameterName, OUT PWSTR ValueBuffer, IN SIZE_T BufferSize); STATIC XTAPI PLIST_ENTRY GetMemoryDescriptors(VOID); STATIC XTAPI PLIST_ENTRY GetSystemResources(VOID); STATIC XTAPI VOID InitializeInitializationBlock(IN PKERNEL_INITIALIZATION_BLOCK Block); /* TEMPORARY FOR COMPATIBILITY WITH C CODE */ STATIC XTAPI PKERNEL_INITIALIZATION_BLOCK GetInitializationBlock(VOID) { return InitializationBlock; } }; } #endif /* __XTOSKRNL_KE_BOOTINFO_HH */ ================================================ FILE: xtoskrnl/includes/ke/crash.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/crash.hh * DESCRIPTION: System shutdown and kernel panic mechanism * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_CRASH_HH #define __XTOSKRNL_KE_CRASH_HH #include /* Kernel Library */ namespace KE { class Crash { public: STATIC XTAPI VOID HaltSystem(VOID); STATIC XTAPI VOID Panic(IN ULONG Code); STATIC XTAPI VOID Panic(IN ULONG Code, IN ULONG_PTR Parameter1, IN ULONG_PTR Parameter2, IN ULONG_PTR Parameter3, IN ULONG_PTR Parameter4); }; } #endif /* __XTOSKRNL_KE_CRASH_HH */ ================================================ FILE: xtoskrnl/includes/ke/dispatch.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/dispatch.hh * DESCRIPTION: Kernel Thread Dispatcher * DEVELOPERS: Rafal Kupiec */ #ifndef __XTOSKRNL_KE_DISPATCH_HH #define __XTOSKRNL_KE_DISPATCH_HH #include /* Kernel Library */ namespace KE { class Dispatcher { public: STATIC XTFASTCALL VOID ExitDispatcher(IN KRUNLEVEL OldRunLevel); STATIC XTFASTCALL BOOLEAN SwitchContext(IN PKTHREAD CurrentThread, IN KRUNLEVEL RunLevel); STATIC XTAPI VOID UpdateRunTime(IN PKTRAP_FRAME TrapFrame, IN KRUNLEVEL RunLevel); private: STATIC XTFASTCALL BOOLEAN SwitchThreadContext(IN PKTHREAD CurrentThread, IN BOOLEAN ApcBypass); STATIC XTFASTCALL BOOLEAN SwitchThreadStack(IN PKTHREAD CurrentThread, IN KRUNLEVEL RunLevel); }; } #endif /* __XTOSKRNL_KE_DISPATCH_HH */ ================================================ FILE: xtoskrnl/includes/ke/dpc.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/dpc.hh * DESCRIPTION: Deferred Procedure Call (DPC) support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_DPC_HH #define __XTOSKRNL_KE_DPC_HH #include /* Kernel Library */ namespace KE { class Dpc { public: STATIC XTAPI VOID InitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DpcRoutine, IN PVOID DpcContext); STATIC XTAPI VOID InitializeThreadedDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DpcRoutine, IN PVOID DpcContext); STATIC XTAPI VOID SetTargetProcessor(IN PKDPC Dpc, IN CCHAR Number); STATIC XTAPI VOID SignalCallDone(IN PVOID SystemArgument); STATIC XTAPI BOOLEAN SignalCallSynchronize(IN PVOID SystemArgument); private: STATIC XTFASTCALL VOID RetireList(IN PKPROCESSOR_CONTROL_BLOCK Prcb); }; } #endif /* __XTOSKRNL_KE_DPC_HH */ ================================================ FILE: xtoskrnl/includes/ke/event.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/event.hh * DESCRIPTION: Kernel events support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_EVENT_HH #define __XTOSKRNL_KE_EVENT_HH #include /* Kernel Library */ namespace KE { class Event { public: STATIC XTAPI VOID ClearEvent(IN PKEVENT Event); STATIC XTAPI VOID InitializeEvent(OUT PKEVENT Event, IN KEVENT_TYPE EventType, IN BOOLEAN InitialState); STATIC XTAPI LONG SetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait); }; } #endif /* __XTOSKRNL_KE_EVENT_HH */ ================================================ FILE: xtoskrnl/includes/ke/guard.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/guard.hh * DESCRIPTION: Kernel synchronization guard * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_GUARD_HH #define __XTOSKRNL_KE_GUARD_HH #include #include /* Kernel Library */ namespace KE { class QueuedSpinLockGuard { private: KSPIN_LOCK_QUEUE_LEVEL QueuedLockLevel; public: QueuedSpinLockGuard(IN OUT KSPIN_LOCK_QUEUE_LEVEL LockLevel) { QueuedLockLevel = LockLevel; KE::SpinLock::AcquireQueuedSpinLock(QueuedLockLevel); } ~QueuedSpinLockGuard() { KE::SpinLock::ReleaseQueuedSpinLock(QueuedLockLevel); } QueuedSpinLockGuard(const QueuedSpinLockGuard&) = delete; QueuedSpinLockGuard& operator=(const QueuedSpinLockGuard&) = delete; }; class SpinLockGuard { private: PKSPIN_LOCK Lock; public: SpinLockGuard(IN OUT PKSPIN_LOCK SpinLock) { Lock = SpinLock; KE::SpinLock::AcquireSpinLock(Lock); } ~SpinLockGuard() { KE::SpinLock::ReleaseSpinLock(Lock); } SpinLockGuard(const SpinLockGuard&) = delete; SpinLockGuard& operator=(const SpinLockGuard&) = delete; }; } #endif /* __XTOSKRNL_KE_GUARD_HH */ ================================================ FILE: xtoskrnl/includes/ke/kprocess.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/kprocess.hh * DESCRIPTION: XT kernel process manipulation support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_KPROCESS_HH #define __XTOSKRNL_KE_KPROCESS_HH #include /* Kernel Library */ namespace KE { class KProcess { private: STATIC EPROCESS InitialProcess; public: STATIC XTAPI PEPROCESS GetInitialProcess(VOID); STATIC XTAPI VOID InitializeProcess(IN OUT PKPROCESS Process, IN KPRIORITY Priority, IN KAFFINITY Affinity, IN PULONG_PTR DirectoryTable, IN BOOLEAN Alignment); }; } #endif /* __XTOSKRNL_KE_KPROCESS_HH */ ================================================ FILE: xtoskrnl/includes/ke/krnlinit.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/krnlinit.hh * DESCRIPTION: XTOS Kernel initialization * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_KRNLINIT_HH #define __XTOSKRNL_KE_KRNLINIT_HH #include /* Kernel Library */ namespace KE { class KernelInit { public: STATIC XTAPI VOID BootstrapApplicationProcessor(IN PPROCESSOR_START_BLOCK StartBlock); STATIC XTAPI VOID InitializeMachine(VOID); STATIC XTAPI VOID SwitchBootStack(VOID); private: STATIC XTAPI VOID BootstrapKernel(VOID); STATIC XTAPI VOID InitializeKernel(VOID); }; } #endif /* __XTOSKRNL_KE_KRNLINIT_HH */ ================================================ FILE: xtoskrnl/includes/ke/kthread.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/kthread.hh * DESCRIPTION: XT kernel thread manipulation support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_KTHREAD_HH #define __XTOSKRNL_KE_KTHREAD_HH #include /* Kernel Library */ namespace KE { class KThread { private: STATIC ETHREAD InitialThread; public: STATIC XTAPI PETHREAD GetInitialThread(VOID); STATIC XTAPI XTSTATUS InitializeThread(IN PKPROCESS Process, IN OUT PKTHREAD Thread, IN PKSYSTEM_ROUTINE SystemRoutine, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext, IN PCONTEXT Context, IN PVOID EnvironmentBlock, IN PVOID Stack, IN BOOLEAN StartThread); STATIC XTAPI VOID StartThread(IN PKTHREAD Thread); private: STATIC XTAPI VOID InitializeThreadContext(IN PKTHREAD Thread, IN PKSYSTEM_ROUTINE SystemRoutine, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext, IN PCONTEXT ContextRecord); STATIC XTAPI VOID SuspendNop(IN PKAPC Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2); STATIC XTAPI VOID SuspendRundown(IN PKAPC Apc); STATIC XTAPI VOID SuspendThread(IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); }; } #endif /* __XTOSKRNL_KE_KTHREAD_HH */ ================================================ FILE: xtoskrnl/includes/ke/kubsan.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/kubsan.hh * DESCRIPTION: Kernel Undefined Behaviour Sanitizer (UBSAN) error reporting handler * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_KUBSAN_HH #define __XTOSKRNL_KE_KUBSAN_HH #include /* Kernel Library */ namespace KE { class KUbsan { private: STATIC BOOLEAN ActiveFrame; public: STATIC XTCDECL VOID HandleDivisionOverflow(PKUBSAN_OVERFLOW_DATA Data, PVOID Lhs, PVOID Rhs); STATIC XTCDECL VOID HandleFloatCastOverflow(PKUBSAN_FLOAT_CAST_OVERFLOW_DATA Data, ULONG_PTR Lhs, ULONG_PTR Rhs); STATIC XTCDECL VOID HandleFunctionTypeMismatch(PKUBSAN_FUNCTION_TYPE_MISMATCH_DATA Data, ULONG_PTR Pointer); STATIC XTCDECL VOID HandleIntegerOverflow(PKUBSAN_OVERFLOW_DATA Data, ULONG_PTR Lhs, ULONG_PTR Rhs); STATIC XTCDECL VOID HandleInvalidBuiltin(PKUBSAN_INVALID_BUILTIN_DATA Data); STATIC XTCDECL VOID HandleMisalignedAccess(PKUBSAN_TYPE_MISMATCH_DATA Data, ULONG_PTR Pointer); STATIC XTCDECL VOID HandleNegateOverflow(PKUBSAN_OVERFLOW_DATA Data, ULONG_PTR OldValue); STATIC XTCDECL VOID HandleNullPointerDereference(PKUBSAN_TYPE_MISMATCH_DATA Data); STATIC XTCDECL VOID HandleObjectSizeMismatch(PKUBSAN_TYPE_MISMATCH_DATA Data, ULONG_PTR Pointer); STATIC XTCDECL VOID HandleOutOfBounds(PKUBSAN_OUT_OF_BOUNDS_DATA Data, ULONG_PTR Index); STATIC XTCDECL VOID HandlePointerOverflow(PKUBSAN_OVERFLOW_DATA Data, ULONG_PTR Lhs, ULONG_PTR Rhs); STATIC XTCDECL VOID HandleShiftOutOfBounds(PKUBSAN_SHIFT_OUT_OF_BOUNDS_DATA Data, ULONG_PTR Lhs, ULONG_PTR Rhs); STATIC XTCDECL VOID HandleTypeMismatch(PKUBSAN_TYPE_MISMATCH_DATA Data, ULONG_PTR Pointer); private: STATIC XTCDECL BOOLEAN CheckReport(PKUBSAN_SOURCE_LOCATION Location); STATIC XTCDECL VOID EnterFrame(PKUBSAN_SOURCE_LOCATION Location, PCCHAR Reason); STATIC XTCDECL LONGLONG GetSignedValue(PKUBSAN_TYPE_DESCRIPTOR Type, PVOID Value); STATIC XTCDECL PCCHAR GetTypeKind(UCHAR TypeCheckKind); STATIC XTCDECL ULONGLONG GetUnsignedValue(PKUBSAN_TYPE_DESCRIPTOR Type, PVOID Value); STATIC XTCDECL VOID LeaveFrame(); }; } #endif /* __XTOSKRNL_KE_KUBSAN_HH */ ================================================ FILE: xtoskrnl/includes/ke/proc.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/proc.hh * DESCRIPTION: Processor-related functionality for the kernel * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_PROC_HH #define __XTOSKRNL_KE_PROC_HH #include /* Kernel Library */ namespace KE { class Processor { private: STATIC ULONG InstalledCpus; STATIC PKPROCESSOR_BLOCK *ProcessorBlocks; public: STATIC XTAPI PKPROCESSOR_BLOCK GetCurrentProcessorBlock(VOID); STATIC XTAPI PKPROCESSOR_CONTROL_BLOCK GetCurrentProcessorControlBlock(VOID); STATIC XTAPI ULONG GetCurrentProcessorNumber(VOID); STATIC XTAPI PKTHREAD GetCurrentThread(VOID); STATIC XTAPI PKPROCESSOR_BLOCK GetProcessorBlock(IN ULONG CpuNumber); STATIC XTAPI XTSTATUS InitializeProcessorBlocks(); STATIC XTAPI VOID RegisterHardwareId(IN ULONG HardwareId); STATIC XTAPI VOID RegisterProcessorBlock(ULONG CpuNumber, PKPROCESSOR_BLOCK ProcessorBlock); STATIC XTAPI VOID SaveProcessorState(OUT PKPROCESSOR_STATE CpuState); }; } #endif /* __XTOSKRNL_KE_PROC_HH */ ================================================ FILE: xtoskrnl/includes/ke/runlevel.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/runlevel.hh * DESCRIPTION: Running Level management support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_RUNLEVEL_HH #define __XTOSKRNL_KE_RUNLEVEL_HH #include /* Kernel Library */ namespace KE { class RunLevel { public: STATIC XTFASTCALL KRUNLEVEL GetCurrentRunLevel(VOID); STATIC XTFASTCALL VOID LowerRunLevel(IN KRUNLEVEL RunLevel); STATIC XTFASTCALL KRUNLEVEL RaiseRunLevel(IN KRUNLEVEL RunLevel); }; class LowerRunLevel { private: KRUNLEVEL PreviousRunLevel; public: LowerRunLevel(KRUNLEVEL RunLevel) { PreviousRunLevel = KE::RunLevel::GetCurrentRunLevel(); KE::RunLevel::LowerRunLevel(RunLevel); } ~LowerRunLevel() { KE::RunLevel::RaiseRunLevel(PreviousRunLevel); } LowerRunLevel(const LowerRunLevel&) = delete; LowerRunLevel& operator=(const LowerRunLevel&) = delete; }; class RaiseRunLevel { private: KRUNLEVEL PreviousRunLevel; public: RaiseRunLevel(KRUNLEVEL RunLevel) { PreviousRunLevel = KE::RunLevel::GetCurrentRunLevel(); KE::RunLevel::RaiseRunLevel(RunLevel); } ~RaiseRunLevel() { KE::RunLevel::LowerRunLevel(PreviousRunLevel); } RaiseRunLevel(const RaiseRunLevel&) = delete; RaiseRunLevel& operator=(const RaiseRunLevel&) = delete; }; } #endif /* __XTOSKRNL_KE_RUNLEVEL_HH */ ================================================ FILE: xtoskrnl/includes/ke/semphore.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/semphore.hh * DESCRIPTION: Semaphores support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_SEMPHORE_HH #define __XTOSKRNL_KE_SEMPHORE_HH #include /* Kernel Library */ namespace KE { class Semaphore { public: STATIC XTAPI VOID InitializeSemaphore(IN PKSEMAPHORE Semaphore, IN LONG Count, IN LONG Limit); STATIC XTAPI LONG ReadState(IN PKSEMAPHORE Semaphore); STATIC XTAPI LONG ReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait); }; } #endif /* __XTOSKRNL_KE_SEMPHORE_HH */ ================================================ FILE: xtoskrnl/includes/ke/shdata.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/shdata.hh * DESCRIPTION: Kernel Shared Data * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_SHDATA_HH #define __XTOSKRNL_KE_SHDATA_HH #include /* Kernel Library */ namespace KE { class SharedData { private: STATIC PKSHARED_DATA KernelSharedData; public: STATIC XTAPI LARGE_INTEGER GetInterruptTime(VOID); STATIC XTAPI PKSHARED_DATA GetKernelSharedData(VOID); STATIC XTAPI LARGE_INTEGER GetSystemTime(VOID); STATIC XTAPI LARGE_INTEGER GetTickCount(VOID); STATIC XTAPI VOID IncrementTickCount(); STATIC XTAPI VOID InitializeKernelSharedData(VOID); STATIC XTAPI VOID SetInterruptTime(IN LARGE_INTEGER Time); STATIC XTAPI VOID SetSystemTime(IN LARGE_INTEGER Time); }; } #endif /* __XTOSKRNL_KE_SHDATA_HH */ ================================================ FILE: xtoskrnl/includes/ke/spinlock.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/spinlock.hh * DESCRIPTION: Spinlocks support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_SPINLOCK_HH #define __XTOSKRNL_KE_SPINLOCK_HH #include /* Kernel Library */ namespace KE { class SpinLock { private: STATIC KSPIN_LOCK DispatcherLockQueue; STATIC KSPIN_LOCK ExpansionLockQueue; STATIC KSPIN_LOCK FileSystemLockQueue; STATIC KSPIN_LOCK IoCancelLockQueue; STATIC KSPIN_LOCK IoCompletionLockQueue; STATIC KSPIN_LOCK IoDatabaseLockQueue; STATIC KSPIN_LOCK IoVpbLockQueue; STATIC KSPIN_LOCK MasterLockQueue; STATIC KSPIN_LOCK NonPagedAllocLockQueue; STATIC KSPIN_LOCK NonPagedPoolLockQueue; STATIC KSPIN_LOCK PfnLockQueue; STATIC KSPIN_LOCK SystemSpaceLockQueue; STATIC KSPIN_LOCK TimerTableLockQueue; STATIC KSPIN_LOCK VacbLockQueue; STATIC KSPIN_LOCK WorkLockQueue; public: STATIC XTFASTCALL VOID AcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_LEVEL LockLevel); STATIC XTFASTCALL VOID AcquireSpinLock(IN OUT PKSPIN_LOCK SpinLock); STATIC XTAPI VOID InitializeAllLocks(); STATIC XTAPI VOID InitializeLockQueues(); STATIC XTAPI VOID InitializeSpinLock(IN PKSPIN_LOCK SpinLock); STATIC XTFASTCALL VOID ReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_LEVEL LockLevel); STATIC XTFASTCALL VOID ReleaseSpinLock(IN OUT PKSPIN_LOCK SpinLock); STATIC XTFASTCALL BOOLEAN TestSpinLock(IN PKSPIN_LOCK SpinLock); }; } #endif /* __XTOSKRNL_KE_SPINLOCK_HH */ ================================================ FILE: xtoskrnl/includes/ke/sysres.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/sysres.hh * DESCRIPTION: System boot resources management * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_SYSRES_HH #define __XTOSKRNL_KE_SYSRES_HH #include /* Kernel Library */ namespace KE { class SystemResources { private: STATIC LIST_ENTRY ResourcesListHead; STATIC KSPIN_LOCK ResourcesLock; public: STATIC XTAPI XTSTATUS AcquireResource(IN SYSTEM_RESOURCE_TYPE ResourceType, OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader); STATIC XTAPI XTSTATUS GetResource(IN SYSTEM_RESOURCE_TYPE ResourceType, OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader); STATIC XTAPI VOID InitializeResources(VOID); STATIC XTAPI VOID ReleaseResource(IN PSYSTEM_RESOURCE_HEADER ResourceHeader); private: STATIC XTAPI XTSTATUS GetSystemResource(IN SYSTEM_RESOURCE_TYPE ResourceType, IN BOOLEAN ResourceLock, OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader); }; } #endif /* __XTOSKRNL_KE_SYSRES_HH */ ================================================ FILE: xtoskrnl/includes/ke/systime.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/systime.hh * DESCRIPTION: Timebase and system clock support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_SYSTIME_HH #define __XTOSKRNL_KE_SYSTIME_HH #include /* Kernel Library */ namespace KE { class SystemTime { private: STATIC LARGE_INTEGER BootTime; STATIC ULONG MaximumIncrement; STATIC ULONG MinimumIncrement; STATIC LONG TickOffset; STATIC ULONG TimeAdjustment; public: STATIC XTAPI VOID GetSystemTime(OUT PLARGE_INTEGER SystemTime); STATIC XTAPI VOID SetSystemTime(IN PLARGE_INTEGER NewTime, OUT PLARGE_INTEGER OldTime, IN BOOLEAN AdjustInterruptTime, IN BOOLEAN WriteToRtc); STATIC XTAPI VOID SetTimeIncrement(IN ULONG MinIncrement, IN ULONG MaxIncrement); STATIC XTFASTCALL VOID UpdateSystemTime(IN PKTRAP_FRAME TrapFrame, IN ULONG Increment, IN KRUNLEVEL RunLevel); }; } #endif /* __XTOSKRNL_KE_SYSTIME_HH */ ================================================ FILE: xtoskrnl/includes/ke/timer.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke/timer.hh * DESCRIPTION: Kernel timer object support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_TIMER_HH #define __XTOSKRNL_KE_TIMER_HH #include /* Kernel Library */ namespace KE { class Timer { public: STATIC XTAPI BOOLEAN CancelTimer(IN PKTIMER Timer); STATIC XTAPI VOID ClearTimer(IN PKTIMER Timer); STATIC XTAPI BOOLEAN GetState(IN PKTIMER Timer); STATIC XTAPI VOID InitializeTimer(OUT PKTIMER Timer, IN KTIMER_TYPE Type); STATIC XTAPI ULONGLONG QueryTimer(IN PKTIMER Timer); STATIC XTAPI VOID SetTimer(IN PKTIMER Timer, IN LARGE_INTEGER DueTime, IN LONG Period, IN PKDPC Dpc); private: STATIC XTAPI VOID RemoveTimer(IN OUT PKTIMER Timer); }; } #endif /* __XTOSKRNL_KE_TIMER_HH */ ================================================ FILE: xtoskrnl/includes/ke.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/ke.hh * DESCRIPTION: Kernel Library * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_KE_HH #define __XTOSKRNL_KE_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif /* __XTOSKRNL_KE_HH */ ================================================ FILE: xtoskrnl/includes/mm/alloc.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/alloc.hh * DESCRIPTION: Memory Manager pool allocator * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_ALLOC_HH #define __XTOSKRNL_MM_ALLOC_HH #include #include /* Memory Manager */ namespace MM { class Allocator final : private Pool { private: STATIC PPOOL_TRACKING_TABLE AllocationsTrackingExpansionTable; STATIC SIZE_T AllocationsTrackingExpansionTableSize; STATIC PPOOL_TRACKING_TABLE AllocationsTrackingTable; STATIC KSPIN_LOCK AllocationsTrackingTableLock; STATIC SIZE_T AllocationsTrackingTableMask; STATIC SIZE_T AllocationsTrackingTableSize; STATIC ULONG BigAllocationsInUse; STATIC PPOOL_TRACKING_BIG_ALLOCATIONS BigAllocationsTrackingTable; STATIC SIZE_T BigAllocationsTrackingTableHash; STATIC KSPIN_LOCK BigAllocationsTrackingTableLock; STATIC SIZE_T BigAllocationsTrackingTableSize; STATIC PPOOL_TRACKING_TABLE TagTables[MM_POOL_TRACKING_TABLES]; public: STATIC XTAPI XTSTATUS AllocatePages(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, OUT PVOID *Memory); STATIC XTAPI XTSTATUS AllocatePool(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, OUT PVOID *Memory); STATIC XTAPI XTSTATUS AllocatePool(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, OUT PVOID *Memory, IN ULONG Tag); STATIC XTAPI XTSTATUS FreePages(IN PVOID VirtualAddress); STATIC XTAPI XTSTATUS FreePages(IN PVOID VirtualAddress, OUT PPFN_NUMBER PagesFreed); STATIC XTAPI XTSTATUS FreePool(IN PVOID VirtualAddress); STATIC XTAPI XTSTATUS FreePool(IN PVOID VirtualAddress, IN ULONG Tag); STATIC XTAPI VOID InitializeAllocationsTracking(VOID); STATIC XTAPI VOID InitializeBigAllocationsTracking(VOID); private: STATIC XTAPI XTSTATUS AllocateNonPagedPoolPages(IN PFN_COUNT Pages, OUT PVOID *Memory); STATIC XTAPI XTSTATUS AllocatePagedPoolPages(IN PFN_COUNT Pages, OUT PVOID *Memory); STATIC XTINLINE ULONG ComputeHash(IN PVOID VirtualAddress); STATIC XTINLINE ULONG ComputeHash(IN ULONG Tag, IN ULONG TableMask); STATIC XTAPI BOOLEAN ExpandBigAllocationsTable(VOID); STATIC XTAPI XTSTATUS FreeNonPagedPoolPages(IN PVOID VirtualAddress, OUT PPFN_NUMBER PagesFreed); STATIC XTAPI XTSTATUS FreePagedPoolPages(IN PVOID VirtualAddress, OUT PPFN_NUMBER PagesFreed); STATIC XTAPI VOID RegisterAllocationTag(IN ULONG Tag, IN SIZE_T Bytes, IN MMPOOL_TYPE PoolType); STATIC XTAPI VOID RegisterAllocationTagExpansion(IN ULONG Tag, IN SIZE_T Bytes, IN MMPOOL_TYPE PoolType); STATIC XTAPI BOOLEAN RegisterBigAllocationTag(IN PVOID VirtualAddress, IN ULONG Tag, IN ULONG Pages, IN MMPOOL_TYPE PoolType); STATIC XTAPI VOID UnregisterAllocationTag(IN ULONG Tag, IN SIZE_T Bytes, IN MMPOOL_TYPE PoolType); STATIC XTAPI VOID UnregisterAllocationTagExpansion(IN ULONG Tag, IN SIZE_T Bytes, IN MMPOOL_TYPE PoolType); STATIC XTAPI ULONG UnregisterBigAllocationTag(IN PVOID VirtualAddress, OUT PULONG_PTR Pages, IN MMPOOL_TYPE PoolType); }; } #endif /* __XTOSKRNL_MM_ALLOC_HH */ ================================================ FILE: xtoskrnl/includes/mm/amd64/pagemap.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/amd64/pagemap.hh * DESCRIPTION: Low-level support for page map manipulation * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_AMD64_PAGEMAP_HH #define __XTOSKRNL_MM_AMD64_PAGEMAP_HH #include /* Memory Manager */ namespace MM { typedef class PageMap { protected: MMPAGEMAP_INFO PageMapInfo; public: XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN LONG Count); XTAPI BOOLEAN CanonicalAddress(IN PVOID VirtualAddress); XTAPI VOID ClearPte(IN PMMPTE PtePointer); XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); XTAPI PMMP5E GetP5eAddress(IN PVOID Address); XTAPI ULONG GetP5eOffset(IN PVOID Address); XTAPI PVOID GetP5eVirtualAddress(IN PMMP5E P5ePointer); XTAPI USHORT GetPageMapLevel(); XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); XTAPI PMMPDE GetPdeAddress(IN PVOID Address); XTAPI ULONG GetPdeOffset(IN PVOID Address); VIRTUAL XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer) = 0; XTAPI PMMPPE GetPpeAddress(IN PVOID Address); XTAPI ULONG GetPpeOffset(IN PVOID Address); VIRTUAL XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer) = 0; XTAPI ULONGLONG GetPte(IN PMMPTE PtePointer); XTAPI PMMPTE GetPteAddress(IN PVOID Address); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); XTAPI ULONG GetPteOffset(IN PVOID Address); XTAPI ULONG GetPteSize(VOID); XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); VIRTUAL XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer) = 0; XTAPI PMMPXE GetPxeAddress(IN PVOID Address); XTAPI ULONG GetPxeOffset(IN PVOID Address); VIRTUAL XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer) = 0; XTAPI BOOLEAN GetXpaStatus(); VIRTUAL XTAPI VOID InitializePageMapInfo(VOID) = 0; XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); XTAPI VOID SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value); XTAPI VOID SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value); XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG AttributesMask); XTAPI VOID SetPte(IN PMMPTE PtePointer, IN ULONGLONG Attributes); XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); XTAPI VOID TransitionPte(IN PMMPTE PointerPte, IN ULONG_PTR Protection); XTAPI VOID WritePte(IN PMMPTE Pte, IN MMPTE Value); } PAGEMAP, *PPAGEMAP; class PageMapBasic final : public PageMap { public: XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer); XTAPI VOID InitializePageMapInfo(VOID); }; class PageMapXpa final : public PageMap { public: XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer); XTAPI VOID InitializePageMapInfo(VOID); }; } #endif /* __XTOSKRNL_MM_AMD64_PAGEMAP_HH */ ================================================ FILE: xtoskrnl/includes/mm/amd64/paging.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/amd64/paging.hh * DESCRIPTION: Low level page management support for AMD64 * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_AMD64_PAGING_HH #define __XTOSKRNL_MM_AMD64_PAGING_HH #include /* Memory Manager */ namespace MM { class Paging { private: STATIC PPAGEMAP PmlRoutines; public: STATIC XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN LONG Count); STATIC XTAPI BOOLEAN CanonicalAddress(IN PVOID VirtualAddress); STATIC XTAPI VOID ClearPte(IN PMMPTE PtePointer); STATIC XTAPI VOID FlushEntireTlb(VOID); STATIC XTAPI VOID FlushTlb(VOID); STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); STATIC XTAPI PMMP5E GetP5eAddress(IN PVOID Address); STATIC XTAPI PVOID GetP5eVirtualAddress(IN PMMP5E P5ePointer); STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); STATIC XTAPI USHORT GetPageMapLevel(); STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); STATIC XTAPI ULONGLONG GetPte(IN PMMPTE PtePointer); STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); STATIC XTAPI ULONG GetPteSize(VOID); STATIC XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); STATIC XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); STATIC XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); STATIC XTAPI PMMPXE GetPxeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer); STATIC XTAPI BOOLEAN GetXpaStatus(VOID); STATIC XTAPI VOID InitializePageMapSupport(VOID); STATIC XTAPI XTSTATUS MapVirtualAddress(IN PVOID VirtualAddress, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG Attributes); STATIC XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); STATIC XTAPI VOID SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value); STATIC XTAPI VOID SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value); STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG AttributesMask); STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer, IN ULONGLONG Attributes); STATIC XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); STATIC XTAPI VOID WritePte(IN PMMPTE Pte, IN MMPTE Value); STATIC XTAPI VOID TransitionPte(IN PMMPTE PointerPte, IN ULONG_PTR Protection); STATIC XTFASTCALL VOID ZeroPages(IN PVOID Address, IN ULONG Size); private: STATIC XTAPI BOOLEAN GetExtendedPhysicalAddressingStatus(VOID); STATIC XTAPI PPAGEMAP GetPageMapBasicRoutines(VOID); STATIC XTAPI PPAGEMAP GetPageMapXpaRoutines(VOID); }; } #endif /* __XTOSKRNL_MM_AMD64_PAGING_HH */ ================================================ FILE: xtoskrnl/includes/mm/amd64/pte.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/amd64/pte.hh * DESCRIPTION: Page Table Entry (PTE) for AMD64 support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_AMD64_PTE_HH #define __XTOSKRNL_MM_AMD64_PTE_HH #include /* Memory Manager */ namespace MM { class Pte { private: STATIC MMPTE FirstSystemFreePte[MaximumPtePoolTypes]; STATIC PMMPTE SystemPteBase; STATIC PMMPTE SystemPtesEnd[MaximumPtePoolTypes]; STATIC PMMPTE SystemPtesStart[MaximumPtePoolTypes]; STATIC PFN_COUNT TotalSystemFreePtes[MaximumPtePoolTypes]; STATIC MMPTE ValidPte; public: STATIC XTAPI BOOLEAN AddressValid(IN PVOID VirtualAddress); STATIC XTAPI PFN_COUNT GetPtesPerPage(VOID); STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); STATIC XTAPI PMMPTE GetValidPte(VOID); STATIC XTAPI VOID InitializePageTable(VOID); STATIC XTAPI VOID InitializeSystemPte(VOID); STATIC XTAPI VOID InitializeSystemPtePool(IN PMMPTE StartingPte, IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE PoolType); STATIC XTAPI VOID InitializeSystemPteSpace(VOID); STATIC XTAPI VOID MapP5E(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMP5E TemplateP5e); STATIC XTAPI VOID MapPDE(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMPDE TemplatePde); STATIC XTAPI VOID MapPPE(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMPPE TemplatePpe); STATIC XTAPI VOID MapPTE(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMPTE TemplatePte); STATIC XTAPI VOID MapPXE(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMPXE TemplatePxe); STATIC XTAPI VOID ReleaseSystemPtes(IN PMMPTE StartingPte, IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); STATIC XTAPI PMMPTE ReserveSystemPtes(IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); private: STATIC XTAPI BOOLEAN FindFreeCluster(IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, OUT PMMPTE *FoundCluster, OUT PMMPTE *PreviousClusterNode); STATIC XTAPI ULONG GetClusterSize(IN PMMPTE Pte); }; } #endif /* __XTOSKRNL_MM_AMD64_PTE_HH */ ================================================ FILE: xtoskrnl/includes/mm/colors.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/colors.hh * DESCRIPTION: Memory manager page coloring subsystem * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_COLORS_HH #define __XTOSKRNL_MM_COLORS_HH #include /* Memory Manager */ namespace MM { class Colors { private: STATIC PMMCOLOR_TABLES FreePages[FreePageList + 1]; STATIC MMPFNLIST ModifiedPages[MM_PAGING_COLORS]; STATIC ULONG PagingColors; STATIC ULONG PagingColorsMask; public: STATIC XTAPI VOID ComputePageColoring(VOID); STATIC XTAPI PMMCOLOR_TABLES GetFreePages(IN MMPAGELISTS PageList, IN ULONG Color); STATIC XTAPI PMMPFNLIST GetModifiedPages(IN ULONG Color); STATIC XTAPI ULONG GetNextColor(VOID); STATIC XTAPI ULONG GetPagingColors(VOID); STATIC XTAPI ULONG GetPagingColorsMask(VOID); STATIC XTAPI VOID InitializeColorTables(VOID); }; } #endif /* __XTOSKRNL_MM_COLORS_HH */ ================================================ FILE: xtoskrnl/includes/mm/guard.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/guard.hh * DESCRIPTION: Memory Manager synchronization guard * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_GUARD_HH #define __XTOSKRNL_MM_GUARD_HH #include #include #include /* Memory Manager */ namespace MM { class PoolLockGuard { private: BOOLEAN Locked; MMPOOL_TYPE LockPoolType; KRUNLEVEL PreviousRunLevel; public: PoolLockGuard(IN MMPOOL_TYPE PoolType) { LockPoolType = PoolType; /* Determine the appropriate synchronization mechanism based on the requested pool type */ if(LockPoolType == NonPagedPool) { /* Elevate the runlevel to DISPATCH_LEVEL */ PreviousRunLevel = KE::RunLevel::RaiseRunLevel(DISPATCH_LEVEL); /* Acquire the global queued spinlock protecting the non-paged pool */ KE::SpinLock::AcquireQueuedSpinLock(NonPagedPoolLock); } else { /* Paged pool requires a mutex, currently unimplemented */ UNIMPLEMENTED; } /* Mark the guard as actively holding the lock */ Locked = TRUE; } ~PoolLockGuard(VOID) { /* Automatically release the held lock upon going out of scope */ Release(); } PoolLockGuard(const PoolLockGuard&) = delete; PoolLockGuard& operator=(const PoolLockGuard&) = delete; VOID Release(VOID) { /* Check if the guard is currently holding a lock */ if(!Locked) { /* Return, to prevent a double-free */ return; } /* Determine the appropriate synchronization mechanism based on the requested pool type */ if(LockPoolType == NonPagedPool) { /* Release the non-paged pool spinlock and subsequently restore the original runlevel */ KE::SpinLock::ReleaseQueuedSpinLock(NonPagedPoolLock); KE::RunLevel::LowerRunLevel(PreviousRunLevel); } else { /* Paged pool requires a mutex, currently unimplemented */ UNIMPLEMENTED; } /* Update the internal state, indicating that the lock is no longer held */ Locked = FALSE; } }; } #endif /* __XTOSKRNL_MM_GUARD_HH */ ================================================ FILE: xtoskrnl/includes/mm/hlpool.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/hlpool.hh * DESCRIPTION: Hardware layer pool memory management * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_HLPOOL_HH #define __XTOSKRNL_MM_HLPOOL_HH #include /* Memory Manager */ namespace MM { class HardwarePool { private: STATIC LOADER_MEMORY_DESCRIPTOR HardwareAllocationDescriptors[MM_HARDWARE_ALLOCATION_DESCRIPTORS]; STATIC PVOID HardwareHeapStart; STATIC ULONG UsedHardwareAllocationDescriptors; public: STATIC XTAPI XTSTATUS AllocateHardwareMemory(IN PFN_NUMBER PageCount, IN BOOLEAN Aligned, IN ULONGLONG MaximumAddress, OUT PPHYSICAL_ADDRESS Buffer); STATIC XTAPI XTSTATUS AllocateRealModeMemory(IN PFN_NUMBER PageCount, OUT PVOID *MemoryAddress); STATIC XTAPI XTSTATUS MapHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress, IN PFN_NUMBER PageCount, IN BOOLEAN FlushTlb, OUT PVOID *VirtualAddress); STATIC XTAPI VOID MarkHardwareMemoryWriteThrough(IN PVOID VirtualAddress, IN PFN_NUMBER PageCount); STATIC XTAPI VOID RemapHardwareMemory(IN PVOID VirtualAddress, IN PHYSICAL_ADDRESS PhysicalAddress, IN BOOLEAN FlushTlb); STATIC XTAPI XTSTATUS UnmapHardwareMemory(IN PVOID VirtualAddress, IN PFN_NUMBER PageCount, IN BOOLEAN FlushTlb); }; } #endif /* __XTOSKRNL_MM_HLPOOL_HH */ ================================================ FILE: xtoskrnl/includes/mm/i686/pagemap.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/i686/pagemap.hh * DESCRIPTION: Low-level support for page map manipulation * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_I686_PAGEMAP_HH #define __XTOSKRNL_MM_I686_PAGEMAP_HH #include /* Memory Manager */ namespace MM { typedef class PageMap { protected: MMPAGEMAP_INFO PageMapInfo; public: VIRTUAL XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN ULONG Count) = 0; XTAPI BOOLEAN CanonicalAddress(IN PVOID VirtualAddress); VIRTUAL XTAPI VOID ClearPte(IN PMMPTE PtePointer) = 0; VIRTUAL XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte) = 0; VIRTUAL XTAPI PMMPTE GetNextPte(IN PMMPTE Pte) = 0; VIRTUAL XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte) = 0; VIRTUAL XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte) = 0; XTAPI USHORT GetPageMapLevel(); XTAPI PMMPDE GetPdeAddress(IN PVOID Address); XTAPI ULONG GetPdeOffset(IN PVOID Address); VIRTUAL XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer) = 0; XTAPI PMMPPE GetPpeAddress(IN PVOID Address); XTAPI ULONG GetPpeOffset(IN PVOID Address); XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); VIRTUAL XTAPI ULONGLONG GetPte(IN PMMPTE PtePointer) = 0; XTAPI PMMPTE GetPteAddress(IN PVOID Address); XTAPI ULONG GetPteOffset(IN PVOID Address); VIRTUAL XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte) = 0; VIRTUAL XTAPI ULONG GetPteSize(VOID) = 0; VIRTUAL XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer) = 0; VIRTUAL XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer) = 0; VIRTUAL XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer) = 0; VIRTUAL XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer) = 0; XTAPI BOOLEAN GetXpaStatus(); VIRTUAL XTAPI VOID InitializePageMapInfo(VOID) = 0; VIRTUAL XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer) = 0; VIRTUAL XTAPI VOID SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value) = 0; VIRTUAL XTAPI VOID SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value) = 0; VIRTUAL XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG AttributesMask) = 0; VIRTUAL XTAPI VOID SetPte(IN PMMPTE PtePointer, IN ULONGLONG Attributes) = 0; VIRTUAL XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) = 0; VIRTUAL XTAPI VOID TransitionPte(IN PMMPTE PointerPte, IN ULONG_PTR Protection) = 0; VIRTUAL XTAPI VOID WritePte(IN PMMPTE Pte, IN MMPTE Value) = 0; } PAGEMAP, *PPAGEMAP; class PageMapBasic final : public PageMap { public: XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN ULONG Count); XTAPI VOID ClearPte(IN PMMPTE PtePointer); XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); XTAPI ULONGLONG GetPte(IN PMMPTE PtePointer); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); XTAPI ULONG GetPteSize(VOID); XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); XTAPI VOID InitializePageMapInfo(VOID); XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); XTAPI VOID SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value); XTAPI VOID SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value); XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG AttributesMask); XTAPI VOID SetPte(IN PMMPTE PtePointer, IN ULONGLONG Attributes); XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); XTAPI VOID TransitionPte(IN PMMPTE PointerPte, IN ULONG_PTR Protection); XTAPI VOID WritePte(IN PMMPTE Pte, IN MMPTE Value); }; class PageMapXpa final : public PageMap { public: XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN ULONG Count); XTAPI VOID ClearPte(IN PMMPTE PtePointer); XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); XTAPI ULONGLONG GetPte(IN PMMPTE PtePointer); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); XTAPI ULONG GetPteSize(VOID); XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); XTAPI VOID InitializePageMapInfo(VOID); XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); XTAPI VOID SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value); XTAPI VOID SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value); XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG AttributesMask); XTAPI VOID SetPte(IN PMMPTE PtePointer, IN ULONGLONG Attributes); XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); XTAPI VOID TransitionPte(IN PMMPTE PointerPte, IN ULONG_PTR Protection); XTAPI VOID WritePte(IN PMMPTE Pte, IN MMPTE Value); }; } #endif /* __XTOSKRNL_MM_I686_PAGEMAP_HH */ ================================================ FILE: xtoskrnl/includes/mm/i686/paging.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/i686/paging.hh * DESCRIPTION: Low level page management support for i686 * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_I686_PAGING_HH #define __XTOSKRNL_MM_I686_PAGING_HH #include /* Memory Manager */ namespace MM { class Paging { private: STATIC PPAGEMAP PmlRoutines; public: STATIC XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN LONG Count); STATIC XTAPI BOOLEAN CanonicalAddress(IN PVOID VirtualAddress); STATIC XTAPI VOID ClearPte(IN PMMPTE PtePointer); STATIC XTAPI VOID FlushEntireTlb(VOID); STATIC XTAPI VOID FlushTlb(VOID); STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); STATIC XTAPI USHORT GetPageMapLevel(); STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); STATIC XTAPI ULONGLONG GetPte(IN PMMPTE PtePointer); STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); STATIC XTAPI ULONG GetPteSize(VOID); STATIC XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); STATIC XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); STATIC XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); STATIC XTAPI BOOLEAN GetXpaStatus(VOID); STATIC XTAPI VOID InitializePageMapSupport(VOID); STATIC XTAPI XTSTATUS MapVirtualAddress(IN PVOID VirtualAddress, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG Attributes); STATIC XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); STATIC XTAPI VOID SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value); STATIC XTAPI VOID SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value); STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG AttributesMask); STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer, IN ULONGLONG Attributes); STATIC XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); STATIC XTAPI VOID WritePte(IN PMMPTE Pte, IN MMPTE Value); STATIC XTAPI VOID TransitionPte(IN PMMPTE PointerPte, IN ULONG_PTR Protection); STATIC XTFASTCALL VOID ZeroPages(IN PVOID Address, IN ULONG Size); private: STATIC XTAPI BOOLEAN GetExtendedPhysicalAddressingStatus(VOID); STATIC XTAPI PPAGEMAP GetPageMapBasicRoutines(VOID); STATIC XTAPI PPAGEMAP GetPageMapXpaRoutines(VOID); }; } #endif /* __XTOSKRNL_MM_I686_PAGING_HH */ ================================================ FILE: xtoskrnl/includes/mm/i686/pte.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/i686/pte.hh * DESCRIPTION: Page Table Entry (PTE) for i686 support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_I686_PTE_HH #define __XTOSKRNL_MM_I686_PTE_HH #include /* Memory Manager */ namespace MM { class Pte { private: STATIC MMPTE FirstSystemFreePte[MaximumPtePoolTypes]; STATIC PMMPTE SystemPteBase; STATIC PMMPTE SystemPtesEnd[MaximumPtePoolTypes]; STATIC PMMPTE SystemPtesStart[MaximumPtePoolTypes]; STATIC PFN_COUNT TotalSystemFreePtes[MaximumPtePoolTypes]; STATIC MMPTE ValidPte; public: STATIC XTAPI BOOLEAN AddressValid(IN PVOID VirtualAddress); STATIC XTAPI PFN_COUNT GetPtesPerPage(VOID); STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); STATIC XTAPI PMMPTE GetValidPte(VOID); STATIC XTAPI VOID InitializePageTable(VOID); STATIC XTAPI VOID InitializeSystemPte(VOID); STATIC XTAPI VOID InitializeSystemPtePool(IN PMMPTE StartingPte, IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE PoolType); STATIC XTAPI VOID InitializeSystemPteSpace(VOID); STATIC XTAPI VOID MapPDE(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMPDE TemplatePde); STATIC XTAPI VOID MapPPE(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMPPE TemplatePpe); STATIC XTAPI VOID MapPTE(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMPTE TemplatePte); STATIC XTAPI VOID ReleaseSystemPtes(IN PMMPTE StartingPte, IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); STATIC XTAPI PMMPTE ReserveSystemPtes(IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); private: STATIC XTAPI BOOLEAN FindFreeCluster(IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, OUT PMMPTE *FoundCluster, OUT PMMPTE *PreviousClusterNode); STATIC XTAPI ULONG GetClusterSize(IN PMMPTE Pte); }; } #endif /* __XTOSKRNL_MM_I686_PTE_HH */ ================================================ FILE: xtoskrnl/includes/mm/kpool.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/hlpool.hh * DESCRIPTION: Kernel pool memory management * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_KPOOL_HH #define __XTOSKRNL_MM_KPOOL_HH #include /* Memory Manager */ namespace MM { class KernelPool { public: STATIC XTAPI XTSTATUS AllocateKernelStack(OUT PVOID *Stack, IN ULONG StackSize); STATIC XTAPI XTSTATUS AllocateProcessorStructures(OUT PVOID *StructuresData); STATIC XTAPI VOID FreeKernelStack(IN PVOID Stack, IN ULONG StackSize); STATIC XTAPI VOID FreeProcessorStructures(IN PVOID StructuresData); }; } #endif /* __XTOSKRNL_MM_KPOOL_HH */ ================================================ FILE: xtoskrnl/includes/mm/mmgr.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/mmgr.hh * DESCRIPTION: Memory Manager * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_MMGR_HH #define __XTOSKRNL_MM_MMGR_HH #include /* Memory Manager */ namespace MM { class Manager { private: STATIC MMMEMORY_LAYOUT MemoryLayout; STATIC PFN_NUMBER NumberOfSystemPtes; STATIC PPHYSICAL_MEMORY_DESCRIPTOR PhysicalMemoryBlock; public: STATIC XTAPI ULONG_PTR GetInstalledMemorySize(VOID); STATIC XTAPI PMMMEMORY_LAYOUT GetMemoryLayout(VOID); STATIC XTAPI PFN_NUMBER GetNumberOfSystemPtes(VOID); STATIC XTAPI PPHYSICAL_MEMORY_DESCRIPTOR GetPhysicalMemoryBlock(VOID); STATIC XTAPI VOID InitializeMemoryLayout(VOID); STATIC XTAPI VOID InitializeMemoryManager(VOID); STATIC XTAPI XTSTATUS MapKernelSharedData(VOID); STATIC XTAPI BOOLEAN VerifyMemoryTypeFree(IN LOADER_MEMORY_TYPE MemoryType); STATIC XTAPI BOOLEAN VerifyMemoryTypeInvisible(IN LOADER_MEMORY_TYPE MemoryType); private: STATIC XTAPI VOID ComputeBootImageSize(OUT PPFN_NUMBER BootImageSize); STATIC XTAPI VOID ComputeMaximumNonPagedPoolSize(OUT PPFN_NUMBER PoolSize); STATIC XTAPI VOID ComputeNonPagedPoolSize(OUT PPFN_NUMBER PoolSize); STATIC XTAPI VOID ComputePagedPoolSize(OUT PPFN_NUMBER PoolSize); STATIC XTAPI VOID ComputeSessionSpaceSize(OUT PPFN_NUMBER SpaceSize); STATIC XTAPI VOID ComputeSystemPteSize(OUT PPFN_NUMBER PteSize); STATIC XTAPI VOID DumpMemoryLayout(VOID); }; } #endif /* __XTOSKRNL_MM_MMGR_HH */ ================================================ FILE: xtoskrnl/includes/mm/pfault.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/pfault.hh * DESCRIPTION: Page fault support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_PFAULT_HH #define __XTOSKRNL_MM_PFAULT_HH #include /* Memory Manager */ namespace MM { class PageFault { public: STATIC XTFASTCALL XTSTATUS CheckPdeForPagedPool(IN PVOID VirtualAddress); }; } #endif /* __XTOSKRNL_MM_PFAULT_HH */ ================================================ FILE: xtoskrnl/includes/mm/pfn.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/pfn.hh * DESCRIPTION: Physical Frame Number (PFN) support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_PFN_HH #define __XTOSKRNL_MM_PFN_HH #include /* Memory Manager */ namespace MM { class Pfn { private: STATIC PFN_NUMBER AvailablePages; STATIC MMPFNLIST BadPagesList; STATIC PLOADER_MEMORY_DESCRIPTOR FreeDescriptor; STATIC MMPFNLIST FreePagesList; STATIC ULONG_PTR HighestPhysicalPage; STATIC PVOID HighestUserAddress; STATIC ULONG_PTR LowestPhysicalPage; STATIC MMPFNLIST ModifiedPagesList; STATIC MMPFNLIST ModifiedReadOnlyPagesList; STATIC ULONGLONG NumberOfPhysicalPages; STATIC LOADER_MEMORY_DESCRIPTOR OriginalFreeDescriptor; STATIC PMMPFNLIST PageLocationList[]; STATIC RTL_BITMAP PfnBitMap; STATIC MMPFNLIST RomPagesList; STATIC MMPFNLIST StandbyPagesList; STATIC MMPFNLIST ZeroedPagesList; public: STATIC XTAPI PFN_NUMBER AllocateBootstrapPages(IN PFN_NUMBER NumberOfPages); STATIC XTAPI PFN_NUMBER AllocatePhysicalPage(IN ULONG Color); STATIC XTAPI VOID ComputePfnDatabaseSize(OUT PPFN_NUMBER DatabaseSize); STATIC XTAPI VOID DecrementReferenceCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex, IN BOOLEAN BeginStandbyList = FALSE); STATIC XTAPI VOID DecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex, IN BOOLEAN BeginStandbyList = FALSE); STATIC XTAPI VOID FreePhysicalPage(IN PMMPTE PointerPte); STATIC XTAPI PFN_NUMBER GetAvailablePages(VOID); STATIC XTAPI ULONG_PTR GetHighestPhysicalPage(VOID); STATIC XTAPI ULONGLONG GetNumberOfPhysicalPages(VOID); STATIC XTAPI PMMPFN GetPfnEntry(IN PFN_NUMBER Pfn); STATIC XTAPI VOID InitializePfnBitmap(VOID); STATIC XTAPI VOID InitializePfnDatabase(VOID); STATIC XTAPI VOID LinkPfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified); STATIC XTAPI VOID LinkPfnWithParent(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN PFN_NUMBER ParentFrame); STATIC XTAPI VOID ScanMemoryDescriptors(VOID); private: STATIC XTAPI VOID DecrementAvailablePages(VOID); STATIC XTAPI VOID IncrementAvailablePages(VOID); STATIC XTAPI VOID InitializePageDirectory(IN PMMPDE StartingPde, IN PMMPDE EndingPde); STATIC XTAPI VOID InitializePageTablePfns(VOID); STATIC XTAPI VOID LinkFreePage(IN PFN_NUMBER PageFrameIndex); STATIC XTAPI VOID LinkPage(IN PMMPFNLIST ListHead, IN PFN_NUMBER PageFrameIndex); STATIC XTAPI VOID LinkPfnForPageTable(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte); STATIC XTFASTCALL VOID LinkStandbyPage(IN PFN_NUMBER PageFrameIndex); STATIC XTAPI VOID ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, IN PFN_NUMBER PageCount, IN LOADER_MEMORY_TYPE MemoryType); STATIC XTAPI VOID ScanPageTable(IN PMMPTE PointerPte, IN ULONG Level); STATIC XTAPI PFN_NUMBER UnlinkFreePage(IN PFN_NUMBER PageFrameIndex, IN ULONG Color); }; } #endif /* __XTOSKRNL_MM_PFN_HH */ ================================================ FILE: xtoskrnl/includes/mm/pool.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/pool.hh * DESCRIPTION: Memory Manager pool manager * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_POOL_HH #define __XTOSKRNL_MM_POOL_HH #include /* Memory Manager */ namespace MM { class Pool { protected: STATIC POOL_DESCRIPTOR NonPagedPoolDescriptor; STATIC PFN_NUMBER NonPagedPoolFrameEnd; STATIC PFN_NUMBER NonPagedPoolFrameStart; STATIC LIST_ENTRY NonPagedPoolFreeList[MM_MAX_FREE_PAGE_LIST_HEADS]; STATIC ULONG PoolSecureCookie; STATIC PPOOL_DESCRIPTOR PoolVector[2]; public: STATIC XTAPI MMPOOL_TYPE DeterminePoolType(IN PVOID VirtualAddress); STATIC XTAPI VOID InitializeNonPagedPool(VOID); STATIC XTAPI VOID InitializePagedPool(VOID); STATIC XTAPI VOID InitializePoolSecurity(VOID); protected: STATIC XTAPI PLIST_ENTRY DecodePoolLink(IN PLIST_ENTRY PoolLink); STATIC XTAPI PLIST_ENTRY EncodePoolLink(IN PLIST_ENTRY PoolLink); STATIC XTAPI PPOOL_HEADER GetPoolBlock(IN PPOOL_HEADER Header, IN SSIZE_T Index); STATIC XTAPI PPOOL_HEADER GetPoolEntry(IN PVOID Payload); STATIC XTAPI PLIST_ENTRY GetPoolFreeBlock(IN PPOOL_HEADER Header); STATIC XTAPI PPOOL_HEADER GetPoolNextBlock(IN PPOOL_HEADER Header); STATIC XTAPI PPOOL_HEADER GetPoolPreviousBlock(IN PPOOL_HEADER Header); STATIC XTAPI VOID InsertPoolHeadList(IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); STATIC XTAPI VOID InsertPoolTailList(IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); STATIC XTAPI BOOLEAN PoolListEmpty(IN PLIST_ENTRY ListHead); STATIC XTAPI VOID RemovePoolEntryList(IN PLIST_ENTRY Entry); STATIC XTAPI PLIST_ENTRY RemovePoolHeadList(IN PLIST_ENTRY ListHead); STATIC XTAPI PLIST_ENTRY RemovePoolTailList(IN PLIST_ENTRY ListHead); STATIC XTAPI VOID VerifyPoolBlocks(IN PVOID Block); STATIC XTAPI VOID VerifyPoolHeader(IN PPOOL_HEADER Entry); STATIC XTAPI VOID VerifyPoolLinks(IN PLIST_ENTRY ListHead); STATIC XTAPI VOID VerifyRunLevel(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, IN PVOID Entry); private: STATIC XTAPI VOID InitializePoolDescriptor(IN PPOOL_DESCRIPTOR Descriptor, IN MMPOOL_TYPE PoolType, IN ULONG Index, IN ULONG Threshold, IN PVOID LockAddress); STATIC XTAPI VOID InitializePoolListHead(IN PLIST_ENTRY ListHead); STATIC XTAPI VOID MapNonPagedPool(VOID); }; } #endif /* __XTOSKRNL_MM_POOL_HH */ ================================================ FILE: xtoskrnl/includes/mm.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm.hh * DESCRIPTION: Memory Manager * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_MM_HH #define __XTOSKRNL_MM_HH #include #include XTOS_ARCH_HEADER(mm, pagemap.hh) #include XTOS_ARCH_HEADER(mm, paging.hh) #include XTOS_ARCH_HEADER(mm, pte.hh) #include #include #include #include #include #include #include #include #include #endif /* __XTOSKRNL_MM_HH */ ================================================ FILE: xtoskrnl/includes/po/idle.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/po/idle.hh * DESCRIPTION: Processor idle functionality support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_PO_IDLE_HH #define __XTOSKRNL_PO_IDLE_HH #include /* Runtime Library */ namespace PO { class Idle { public: STATIC XTAPI VOID InitializeProcessorIdleState(IN OUT PKPROCESSOR_CONTROL_BLOCK Prcb); private: STATIC XTFASTCALL VOID Idle0Function(IN PPROCESSOR_POWER_STATE PowerState); STATIC XTAPI VOID PerfIdle(IN PPROCESSOR_POWER_STATE PowerState); STATIC XTAPI VOID PerfIdleDpc(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); }; } #endif /* __XTOSKRNL_PO_IDLE_HH */ ================================================ FILE: xtoskrnl/includes/po.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/po.hh * DESCRIPTION: Power Management * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_PO_HH #define __XTOSKRNL_PO_HH #include #include #endif /* __XTOSKRNL_PO_HH */ ================================================ FILE: xtoskrnl/includes/rtl/amd64/intrin.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/amd64/intrin.hh * DESCRIPTION: Compiler intrinsic support routines * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_RTL_AMD64_INTRIN_HH #define __XTOSKRNL_RTL_AMD64_INTRIN_HH #include /* Forward declarations enforcing the XTAPI calling convention and preserving the raw unmangled symbol names */ #endif /* __XTOSKRNL_RTL_AMD64_INTRIN_HH */ ================================================ FILE: xtoskrnl/includes/rtl/atomic.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/atomic.hh * DESCRIPTION: Atomic operations support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_RTL_ATOMIC_HH #define __XTOSKRNL_RTL_ATOMIC_HH #include /* Runtime Library */ namespace RTL { class Atomic { public: STATIC XTFASTCALL CHAR And8(IN PCHAR Address, IN CHAR Mask); STATIC XTFASTCALL SHORT And16(IN PSHORT Address, IN SHORT Mask); STATIC XTFASTCALL LONG And32(IN PLONG Address, IN LONG Mask); STATIC XTFASTCALL LONG_PTR And64(IN PLONG_PTR Address, IN LONG_PTR Mask); STATIC XTFASTCALL UCHAR BitTestAndSet(IN PLONG Base, IN LONG Offset); STATIC XTFASTCALL UCHAR BitTestAndSet64(IN PLONGLONG Base, IN LONGLONG Offset); STATIC XTFASTCALL CHAR CompareExchange8(IN PCHAR Address, IN CHAR Comperand, IN CHAR Exchange); STATIC XTFASTCALL SHORT CompareExchange16(IN PSHORT Address, IN SHORT Comperand, IN SHORT Exchange); STATIC XTFASTCALL LONG CompareExchange32(IN PLONG Address, IN LONG Comperand, IN LONG Exchange); STATIC XTFASTCALL LONG_PTR CompareExchange64(IN PLONG_PTR Address, IN LONG_PTR Comperand, IN LONG_PTR Exchange); STATIC XTFASTCALL PVOID CompareExchangePointer(IN PVOID *Address, IN PVOID Comperand, IN PVOID Exchange); STATIC XTFASTCALL CHAR Decrement8(IN PCHAR Address); STATIC XTFASTCALL SHORT Decrement16(IN PSHORT Address); STATIC XTFASTCALL LONG Decrement32(IN PLONG Address); STATIC XTFASTCALL LONG_PTR Decrement64(IN PLONG_PTR Address); STATIC XTFASTCALL CHAR Exchange8(IN PCHAR Address, IN CHAR Exchange); STATIC XTFASTCALL SHORT Exchange16(IN PSHORT Address, IN SHORT Exchange); STATIC XTFASTCALL LONG Exchange32(IN PLONG Address, IN LONG Exchange); STATIC XTFASTCALL LONG_PTR Exchange64(IN PLONG_PTR Address, IN LONG_PTR Exchange); STATIC XTFASTCALL CHAR ExchangeAdd8(IN PCHAR Address, IN CHAR Value); STATIC XTFASTCALL SHORT ExchangeAdd16(IN PSHORT Address, IN SHORT Value); STATIC XTFASTCALL LONG ExchangeAdd32(IN PLONG Address, IN LONG Value); STATIC XTFASTCALL LONG_PTR ExchangeAdd64(IN PLONG_PTR Address, IN LONG_PTR Value); STATIC XTFASTCALL PVOID ExchangePointer(IN PVOID *Address, IN PVOID Exchange); STATIC XTFASTCALL PSINGLE_LIST_ENTRY FlushSingleList(IN PSINGLE_LIST_HEADER Header); STATIC XTFASTCALL CHAR Increment8(IN PCHAR Address); STATIC XTFASTCALL SHORT Increment16(IN PSHORT Address); STATIC XTFASTCALL LONG Increment32(IN PLONG Address); STATIC XTFASTCALL LONG_PTR Increment64(IN PLONG_PTR Address); STATIC XTFASTCALL CHAR Or8(IN PCHAR Address, IN CHAR Mask); STATIC XTFASTCALL SHORT Or16(IN PSHORT Address, IN SHORT Mask); STATIC XTFASTCALL LONG Or32(IN PLONG Address, IN LONG Mask); STATIC XTFASTCALL LONG_PTR Or64(IN PLONG_PTR Address, IN LONG_PTR Mask); STATIC XTFASTCALL XTFASTCALL PSINGLE_LIST_ENTRY PopEntrySingleList(IN PSINGLE_LIST_HEADER Header); STATIC XTFASTCALL PSINGLE_LIST_ENTRY PushEntrySingleList(IN PSINGLE_LIST_HEADER Header, IN PSINGLE_LIST_ENTRY Entry); STATIC XTFASTCALL CHAR Xor8(IN PCHAR Address, IN CHAR Mask); STATIC XTFASTCALL SHORT Xor16(IN PSHORT Address, IN SHORT Mask); STATIC XTFASTCALL LONG Xor32(IN PLONG Address, IN LONG Mask); STATIC XTFASTCALL LONG_PTR Xor64(IN PLONG_PTR Address, IN LONG_PTR Mask); }; } #endif /* __XTOSKRNL_RTL_ATOMIC_HH */ ================================================ FILE: xtoskrnl/includes/rtl/bitmap.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/bitmap.hh * DESCRIPTION: Bit maps support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_RTL_BITMAP_HH #define __XTOSKRNL_RTL_BITMAP_HH #include /* Runtime Library */ namespace RTL { class BitMap { public: STATIC XTAPI VOID ClearAllBits(IN PRTL_BITMAP BitMap); STATIC XTAPI VOID ClearBit(IN PRTL_BITMAP BitMap, IN ULONG_PTR Bit); STATIC XTAPI VOID ClearBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR StartingIndex, IN ULONG_PTR Length); STATIC XTAPI ULONG ClearSetBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index); STATIC XTAPI VOID DumpBitMap(IN PRTL_BITMAP BitMap); STATIC XTAPI ULONG_PTR FindClearBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index); STATIC XTAPI ULONG_PTR FindSetBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index); STATIC XTAPI VOID InitializeBitMap(IN PRTL_BITMAP BitMap, IN PULONG_PTR Buffer, IN ULONG Size); STATIC XTAPI VOID SetAllBits(IN PRTL_BITMAP BitMap); STATIC XTAPI VOID SetBit(IN PRTL_BITMAP BitMap, IN ULONG_PTR Bit); STATIC XTAPI VOID SetBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR StartingIndex, IN ULONG_PTR Length); STATIC XTAPI ULONG SetClearBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index); STATIC XTAPI BOOLEAN TestBit(IN PRTL_BITMAP BitMap, IN ULONG_PTR Bit); private: STATIC XTAPI ULONG_PTR CountBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR StartingIndex, IN BOOLEAN SetBits); STATIC XTAPI ULONG_PTR FindBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR StartingIndex, IN BOOLEAN SetBits); }; } #endif /* __XTOSKRNL_RTL_BITMAP_HH */ ================================================ FILE: xtoskrnl/includes/rtl/dispatch.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/dispatch.hh * DESCRIPTION: Dispatching support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_RTL_DISPATCH_HH #define __XTOSKRNL_RTL_DISPATCH_HH #include /* Runtime Library */ namespace RTL { class Dispatcher { public: STATIC XTAPI VOID GetStackLimits(OUT PULONG_PTR StackBase, OUT PULONG_PTR StackLimit); }; } #endif /* __XTOSKRNL_RTL_DISPATCH_HH */ ================================================ FILE: xtoskrnl/includes/rtl/endian.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/endian.hh * DESCRIPTION: Endian conversion routines * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_RTL_ENDIAN_HH #define __XTOSKRNL_RTL_ENDIAN_HH #include /* Runtime Library */ namespace RTL { class Endianness { public: STATIC XTFASTCALL USHORT SwapByte16(IN USHORT Source); STATIC XTFASTCALL ULONG SwapByte32(IN ULONG Source); STATIC XTFASTCALL ULONGLONG SwapByte64(IN ULONGLONG Source); }; } #endif /* __XTOSKRNL_RTL_ENDIAN_HH */ ================================================ FILE: xtoskrnl/includes/rtl/guid.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/guid.hh * DESCRIPTION: Endian conversion routines * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_RTL_GUID_HH #define __XTOSKRNL_RTL_GUID_HH #include /* Runtime Library */ namespace RTL { class Guid { public: STATIC XTAPI BOOLEAN CompareGuids(IN PGUID Guid1, IN PGUID Guid2); }; } #endif /* __XTOSKRNL_RTL_GUID_HH */ ================================================ FILE: xtoskrnl/includes/rtl/i686/intrin.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/i686/intrin.hh * DESCRIPTION: Compiler intrinsic support routines * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_RTL_I686_INTRIN_HH #define __XTOSKRNL_RTL_I686_INTRIN_HH #include /* Forward declarations enforcing the XTAPI calling convention and preserving the raw unmangled symbol names */ XTCLINK XTAPI LONGLONG _alldiv(IN LONGLONG Dividend, IN LONGLONG Divisor) XTSYMBOL("__alldiv"); XTCLINK XTAPI LONGLONG _alldvrm(IN LONGLONG Dividend, IN LONGLONG Divisor, OUT PLONGLONG Remainder) XTSYMBOL("__alldvrm"); XTCLINK XTAPI LONGLONG _allrem(IN LONGLONG Dividend, IN LONGLONG Divisor) XTSYMBOL("__allrem"); XTCLINK XTAPI ULONGLONG _aulldiv(IN ULONGLONG Dividend, IN ULONGLONG Divisor) XTSYMBOL("__aulldiv"); XTCLINK XTAPI ULONGLONG _aulldvrm(IN ULONGLONG Dividend, IN ULONGLONG Divisor, OUT PULONGLONG Remainder) XTSYMBOL("__aulldvrm"); XTCLINK XTAPI ULONGLONG _aullrem(IN ULONGLONG Dividend, IN ULONGLONG Divisor) XTSYMBOL("__aullrem"); #endif /* __XTOSKRNL_RTL_I686_INTRIN_HH */ ================================================ FILE: xtoskrnl/includes/rtl/llist.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/llist.hh * DESCRIPTION: Linked list manipulation routines * DEVELOPERS: Aiken Harris * Rafal Kupiec */ #ifndef __XTOSKRNL_RTL_LLIST_HH #define __XTOSKRNL_RTL_LLIST_HH #include /* Runtime Library */ namespace RTL { class LinkedList { public: STATIC XTCDECL PLIST_ENTRY GetFirstEntry(IN PLIST_ENTRY ListHead); STATIC XTCDECL VOID InitializeListHead(IN PLIST_ENTRY ListHead); STATIC XTCDECL VOID InitializeListHead32(IN PLIST_ENTRY32 ListHead); STATIC XTCDECL VOID InsertHeadList(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); STATIC XTCDECL VOID InsertTailList(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); STATIC XTCDECL BOOLEAN ListEmpty(IN PLIST_ENTRY ListHead); STATIC XTCDECL BOOLEAN ListLoop(IN PLIST_ENTRY ListHead); STATIC XTCDECL VOID RemoveEntryList(IN PLIST_ENTRY Entry); STATIC XTCDECL VOID SpliceHeadList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY SpliceList); STATIC XTCDECL VOID SpliceTailList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY SpliceList); }; } #endif /* __XTOSKRNL_RTL_LLIST_HH */ ================================================ FILE: xtoskrnl/includes/rtl/math.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/math.hh * DESCRIPTION: Kernel math support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_RTL_MATH_HH #define __XTOSKRNL_RTL_MATH_HH #include /* Runtime Library */ namespace RTL { class Math { public: STATIC XTAPI LARGE_INTEGER ConvertToLargeInteger32(IN LONG Value); STATIC XTAPI LARGE_INTEGER ConvertToLargeIntegerUnsigned32(IN ULONG Value); STATIC XTAPI INT CountLeadingZeroes32(IN ULONG Value); STATIC XTAPI INT CountLeadingZeroes64(IN ULONGLONG Value); STATIC XTAPI INT CountTrailingZeroes32(IN ULONG Value); STATIC XTAPI INT CountTrailingZeroes64(IN ULONGLONG Value); STATIC XTAPI LONGLONG Divide32(IN LONG Dividend, IN LONG Divisor, OUT PLONG Remainder); STATIC XTAPI LONGLONG Divide64(IN LONGLONG Dividend, IN LONGLONG Divisor, OUT PLONGLONG Remainder); STATIC XTAPI ULONGLONG DivideUnsigned32(IN ULONG Dividend, IN ULONG Divisor, OUT PULONG Remainder); STATIC XTAPI ULONGLONG DivideUnsigned64(IN ULONGLONG Dividend, IN ULONGLONG Divisor, OUT PULONGLONG Remainder); STATIC XTAPI LARGE_INTEGER DivideLargeInteger(IN LARGE_INTEGER Dividend, IN ULONG Divisor, OUT PULONG Remainder); STATIC XTAPI LONG GetBaseExponent(IN DOUBLE Value, OUT PDOUBLE PowerOfTen); STATIC XTAPI BOOLEAN InfiniteDouble(IN DOUBLE Value); STATIC XTAPI LARGE_INTEGER MultiplyLargeInteger(IN LARGE_INTEGER Multiplicand, IN LONG Multiplier); STATIC XTAPI BOOLEAN NanDouble(IN DOUBLE Value); }; } #endif /* __XTOSKRNL_RTL_MATH_HH */ ================================================ FILE: xtoskrnl/includes/rtl/memory.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/memory.hh * DESCRIPTION: Memory related routines * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_RTL_MEMORY_HH #define __XTOSKRNL_RTL_MEMORY_HH #include /* Runtime Library */ namespace RTL { class Memory { public: STATIC XTAPI SIZE_T CompareMemory(IN PCVOID LeftBuffer, IN PCVOID RightBuffer, IN SIZE_T Length); STATIC XTAPI VOID CopyMemory(OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length); STATIC XTAPI VOID MoveMemory(OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length); STATIC XTAPI BOOLEAN SameMemory(IN PCVOID LeftBuffer, IN PCVOID RightBuffer, IN SIZE_T Length); STATIC XTAPI VOID SetMemory(OUT PVOID Destination, IN UCHAR Byte, IN SIZE_T Length); STATIC XTAPI VOID ZeroMemory(OUT PVOID Destination, IN SIZE_T Length); }; } #endif /* __XTOSKRNL_RTL_MEMORY_HH */ ================================================ FILE: xtoskrnl/includes/rtl/sha1.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/sha1.hh * DESCRIPTION: SHA1 computation support * DEVELOPERS: Rafal Kupiec */ #ifndef __XTOSKRNL_RTL_SHA1_HH #define __XTOSKRNL_RTL_SHA1_HH #include /* Runtime Library */ namespace RTL { class SHA1 { public: STATIC XTAPI XTSTATUS ComputeDigest(IN PCUCHAR Buffer, IN SIZE_T BufferSize, OUT PUCHAR Digest); private: STATIC XTAPI VOID ComputeHash(IN OUT PRTL_SHA1_CONTEXT Context, OUT PUCHAR Digest); STATIC XTAPI VOID HashData(IN OUT PRTL_SHA1_CONTEXT Context, IN PCUCHAR Data, IN ULONG Length); STATIC XTAPI XTSTATUS InitializeContext(OUT PRTL_SHA1_CONTEXT Context); STATIC XTAPI VOID TransformData(IN OUT PULONG State, IN PCUCHAR Buffer); }; } #endif /* __XTOSKRNL_RTL_SHA1_HH */ ================================================ FILE: xtoskrnl/includes/rtl/slist.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/slist.hh * DESCRIPTION: Singly linked list manipulation routines * DEVELOPERS: Rafal Kupiec */ #ifndef __XTOSKRNL_RTL_SLIST_HH #define __XTOSKRNL_RTL_SLIST_HH #include /* Runtime Library */ namespace RTL { class SinglyList { public: STATIC XTCDECL PSINGLE_LIST_ENTRY GetFirstEntry(IN PSINGLE_LIST_HEADER ListHead); STATIC XTCDECL VOID InitializeListHead(IN PSINGLE_LIST_HEADER ListHead); STATIC XTCDECL PSINGLE_LIST_ENTRY InsertHeadList(IN OUT PSINGLE_LIST_HEADER ListHead, IN PSINGLE_LIST_ENTRY Entry); STATIC XTCDECL PSINGLE_LIST_ENTRY InsertTailList(IN OUT PSINGLE_LIST_HEADER ListHead, IN PSINGLE_LIST_ENTRY Entry); STATIC XTCDECL BOOLEAN ListEmpty(IN PSINGLE_LIST_HEADER ListHead); STATIC XTAPI USHORT QueryListDepth(IN PSINGLE_LIST_HEADER ListHead); STATIC XTCDECL VOID RemoveEntryList(IN PSINGLE_LIST_HEADER ListHead, IN PSINGLE_LIST_ENTRY Entry); STATIC XTCDECL PSINGLE_LIST_ENTRY SpliceHeadList(IN OUT PSINGLE_LIST_HEADER ListHead, IN OUT PSINGLE_LIST_HEADER SpliceList); STATIC XTCDECL PSINGLE_LIST_ENTRY SpliceTailList(IN OUT PSINGLE_LIST_HEADER ListHead, IN OUT PSINGLE_LIST_HEADER SpliceList); STATIC XTCDECL PSINGLE_LIST_ENTRY TakeFirstEntry(IN PSINGLE_LIST_HEADER ListHead); }; } #endif /* __XTOSKRNL_RTL_SLIST_HH */ ================================================ FILE: xtoskrnl/includes/rtl/string.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/string.hh * DESCRIPTION: String support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_RTL_STRING_HH #define __XTOSKRNL_RTL_STRING_HH #include /* Runtime Library */ namespace RTL { class String { public: STATIC XTAPI SIZE_T CompareString(IN PCSTR String1, IN PCSTR String2, IN SIZE_T Length); STATIC XTAPI SIZE_T CompareStringInsensitive(IN PCSTR String1, IN PCSTR String2, IN SIZE_T Length); STATIC XTAPI PCHAR ConcatenateString(OUT PCHAR Destination, IN PCHAR Source, IN SIZE_T Count); STATIC XTAPI VOID CopyString(IN PCHAR Destination, IN PCSTR Source, IN ULONG Length); STATIC XTAPI PCSTR FindString(IN PCSTR Source, IN PCSTR Search); STATIC XTAPI PCSTR FindStringInsensitive(IN PCSTR Source, IN PCSTR Search); STATIC XTAPI VOID ReverseString(IN OUT PCHAR String, IN ULONG Length); STATIC XTAPI SIZE_T StringLength(IN PCSTR String, IN SIZE_T MaxLength); STATIC XTAPI XTSTATUS StringToNumber(IN PCSTR String, IN ULONG Base, OUT PULONG Value); STATIC XTAPI SIZE_T StringToWideString(OUT PWCHAR Destination, IN PCSTR *Source, IN SIZE_T Length); STATIC XTAPI PCHAR TokenizeString(IN PCHAR String, IN PCSTR Delimiter, IN OUT PCHAR *SavePtr); STATIC XTAPI CHAR ToLowerCharacter(IN CHAR Character); STATIC XTAPI CHAR ToUpperCharacter(IN CHAR Character); STATIC XTAPI PCHAR TrimLeftString(IN PCHAR String); STATIC XTAPI PCHAR TrimRightString(IN PCHAR String); STATIC XTAPI PCHAR TrimString(IN PCHAR String); }; } #endif /* __XTOSKRNL_RTL_STRING_HH */ ================================================ FILE: xtoskrnl/includes/rtl/time.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/time.hh * DESCRIPTION: Time conversion support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_RTL_TIME_HH #define __XTOSKRNL_RTL_TIME_HH #include /* Runtime Library */ namespace RTL { class Time { private: STATIC CUSHORT DaysInMonth[2][12]; public: STATIC XTAPI XTSTATUS TimeFieldsToUnixEpoch(IN PTIME_FIELDS TimeFields, OUT PLONGLONG UnixTime); STATIC XTAPI XTSTATUS TimeFieldsToXtEpoch(IN PTIME_FIELDS TimeFields, OUT PLARGE_INTEGER XtTime); STATIC XTAPI XTSTATUS UnixEpochToTimeFields(IN PLONGLONG UnixTime, OUT PTIME_FIELDS TimeFields); STATIC XTAPI XTSTATUS XtEpochToTimeFields(IN PLARGE_INTEGER XtTime, OUT PTIME_FIELDS TimeFields); private: STATIC XTFASTCALL BOOLEAN LeapYear(SHORT Year); }; } #endif /* __XTOSKRNL_RTL_TIME_HH */ ================================================ FILE: xtoskrnl/includes/rtl/widestr.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl/widestr.hh * DESCRIPTION: Wide string support * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_RTL_WIDESTR_HH #define __XTOSKRNL_RTL_WIDESTR_HH #include /* Runtime Library */ namespace RTL { class WideString { public: STATIC XTAPI SIZE_T CompareWideString(IN PCWSTR String1, IN PCWSTR String2, IN SIZE_T Length); STATIC XTAPI SIZE_T CompareWideStringInsensitive(IN PCWSTR String1, IN PCWSTR String2, IN SIZE_T Length); STATIC XTAPI PWCHAR ConcatenateWideString(OUT PWCHAR Destination, IN PWCHAR Source, IN SIZE_T Count); STATIC XTAPI VOID CopyWideString(IN PWCHAR Destination, IN PCWSTR Source, IN ULONG Length); STATIC XTAPI PCWSTR FindWideString(IN PCWSTR Source, IN PCWSTR Search); STATIC XTAPI PCWSTR FindWideStringInsensitive(IN PCWSTR Source, IN PCWSTR Search); STATIC XTAPI XTSTATUS FormatWideString(IN PRTL_PRINT_CONTEXT Context, IN PCWSTR Format, IN VA_LIST ArgumentList); STATIC XTAPI VOID ReverseWideString(IN OUT PWCHAR String, IN ULONG Length); STATIC XTAPI PWCHAR TokenizeWideString(IN PWCHAR String, IN PCWSTR Delimiter, IN OUT PWCHAR *SavePtr); STATIC XTAPI WCHAR ToLowerWideCharacter(IN WCHAR Character); STATIC XTAPI WCHAR ToUpperWideCharacter(IN WCHAR Character); STATIC XTAPI PWCHAR TrimLeftWideString(IN PWCHAR String); STATIC XTAPI PWCHAR TrimRightWideString(IN PWCHAR String); STATIC XTAPI PWCHAR TrimWideString(IN PWCHAR String); STATIC XTAPI SIZE_T WideStringLength(IN PCWSTR String, IN SIZE_T MaxLength); STATIC XTAPI XTSTATUS WideStringToNumber(IN PCWSTR String, IN ULONG Base, OUT PULONG Value); private: STATIC XTAPI XTSTATUS FormatArgumentSpecifier(IN PRTL_PRINT_CONTEXT Context, IN PCWSTR Format, IN PVA_LIST ArgumentList, IN OUT PULONG Index); STATIC XTAPI ULONGLONG GetArgument(IN PVA_LIST ArgumentList, IN ULONG ArgumentNumber, IN LONG ArgumentSize); STATIC XTAPI ULONGLONG GetSpecifierValue(IN PWCHAR *Format); STATIC XTAPI XTSTATUS WriteWideCharacter(IN PRTL_PRINT_CONTEXT Context, IN WCHAR Character); STATIC XTCDECL XTSTATUS WriteCustomValue(IN PRTL_PRINT_CONTEXT Context, IN PCWSTR Format, IN ...); STATIC XTAPI XTSTATUS WriteDoubleValue(IN PRTL_PRINT_CONTEXT Context, IN PRTL_PRINT_FORMAT_PROPERTIES FormatProperties, IN DOUBLE Value); STATIC XTAPI XTSTATUS WriteHexDoubleValue(IN PRTL_PRINT_CONTEXT Context, IN PRTL_PRINT_FORMAT_PROPERTIES FormatProperties, IN DOUBLE Double); STATIC XTAPI XTSTATUS WriteIntegerValue(IN PRTL_PRINT_CONTEXT Context, IN PRTL_PRINT_FORMAT_PROPERTIES FormatProperties, IN ULONGLONG Integer); STATIC XTAPI XTSTATUS WriteStringValue(PRTL_PRINT_CONTEXT Context, PRTL_PRINT_FORMAT_PROPERTIES FormatProperties, PCSTR String, SIZE_T StringLength); STATIC XTAPI XTSTATUS WriteValue(PRTL_PRINT_CONTEXT Context, PRTL_PRINT_FORMAT_PROPERTIES FormatProperties, PCWSTR String, SIZE_T StringLength); }; } #endif /* __XTOSKRNL_RTL_WIDESTR_HH */ ================================================ FILE: xtoskrnl/includes/rtl.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/rtl.hh * DESCRIPTION: Runtime Library * DEVELOPERS: Aiken Harris */ #ifndef __XTOSKRNL_RTL_HH #define __XTOSKRNL_RTL_HH #include #include XTOS_ARCH_HEADER(rtl, intrin.hh) #include #include #include #include #include #include #include #include #include #include #include #include #include #endif /* __XTOSKRNL_RTL_HH */ ================================================ FILE: xtoskrnl/includes/xtos.hh ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/xtos.hh * DESCRIPTION: Top level header for the XT kernel * DEVELOPERS: Aiken Harris */ /* Preprocessor macro for including arch-specific headers */ #define XTOS_ARCH_HEADER(subsystem, header) STRINGIFY(subsystem/_ARCH/header) /* XT Kernel Mode Development Kit */ #include /* XT OS version */ #include /* Kernel specific headers */ #include #include #include #include #include #include #include #include ================================================ FILE: xtoskrnl/kd/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/kd/globals.cc * DESCRIPTION: Kernel Debugger global and static data * DEVELOPERS: Aiken Harris */ #include /* Debug I/O spinlock */ KSPIN_LOCK KD::DebugIo::DebugIoLock; /* Kernel Debugger mode */ KD_DEBUG_MODE KD::DebugIo::DebugMode; /* Debugger I/O providers initialization routines */ PKD_INIT_ROUTINE KD::DebugIo::IoProvidersInitRoutines[KDBG_PROVIDERS_COUNT] = { InitializeFrameBufferProvider, InitializeSerialPortProvider }; /* Pointer to DbgPrint() routine */ PKD_PRINT_ROUTINE KD::DebugIo::KdPrint = NULLPTR; /* List of active I/O providers */ LIST_ENTRY KD::DebugIo::Providers; /* Debugger's serial port handle */ CPPORT KD::DebugIo::SerialPort; /* Pre-defined serial port addresses */ ULONG KD::DebugIo::SerialPortList[COMPORT_COUNT] = COMPORT_ADDRESS; ================================================ FILE: xtoskrnl/kd/dbgio.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/kd/dbgio.cc * DESCRIPTION: Kernel Debugger I/O routines * DEVELOPERS: Aiken Harris */ #include /** * Prints a formatted string using the configured debug output providers. * * @param Format * Supplies the format string. * * @param ... * Supplies the variable argument list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KD::DebugIo::DbgPrint(PCWSTR Format, ...) { VA_LIST Arguments; /* Initialise the va_list */ VA_START(Arguments, Format); /* Call the actual debug print routine */ DbgPrint(Format, Arguments); /* Clean up the va_list */ VA_END(Arguments); } /** * Prints a formatted string using the configured debug output providers (va_list variant). * * @param Format * Supplies the format string. * * @param ... * Supplies the variable argument list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KD::DebugIo::DbgPrint(PCWSTR Format, VA_LIST Arguments) { PLIST_ENTRY DispatchTableEntry; PKD_DISPATCH_TABLE DispatchTable; /* Raise runlevel and acquire the Debug I/O lock */ KE::RaiseRunLevel RunLevel(HIGH_LEVEL); KE::SpinLockGuard SpinLock(&DebugIoLock); /* Iterate over all registered debug providers */ DispatchTableEntry = Providers.Flink; while(DispatchTableEntry != &Providers) { /* Get dispatch table */ DispatchTable = CONTAIN_RECORD(DispatchTableEntry, KD_DISPATCH_TABLE, ListEntry); /* Print formatted string using the provider's print context */ RTL::WideString::FormatWideString(&DispatchTable->PrintContext, (PWCHAR)Format, Arguments); /* Move to the next provider */ DispatchTableEntry = DispatchTableEntry->Flink; } } /** * Detects and enables the kernel's debug ports based on the 'DEBUG' parameter passed to the kernel. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS KD::DebugIo::DetectDebugPorts(VOID) { PCWSTR DebugOption; XTSTATUS Status; /* Get debug parameter */ Status = KE::BootInformation::GetKernelParameter(L"DEBUG", &DebugOption); if(Status != STATUS_SUCCESS) { /* Debug parameter not found, disable debugging */ DebugMode.Enabled = FALSE; return Status; } /* Skip parameter name and check if it is set */ DebugOption += 5; if(*DebugOption != L'=') { /* Debug parameter not set, disable debugging */ DebugMode.Enabled = FALSE; return STATUS_INVALID_PARAMETER; } /* Skip '=' symbol */ DebugOption++; /* Iterate over all debug ports */ while(*DebugOption != L'\0' && *DebugOption != L' ') { /* Check what port is set for debugging */ if(RTL::WideString::CompareWideStringInsensitive(DebugOption, L"COM", 3) == 0) { /* Enable serial port debugging mode */ DebugMode.Mode |= DEBUG_PROVIDER_COMPORT; /* Read COM port number */ DebugOption += 3; while(*DebugOption >= '0' && *DebugOption <= '9') { /* Get port number */ DebugMode.ComPortNumber *= 10; DebugMode.ComPortNumber += *DebugOption - '0'; DebugOption++; } /* Check if custom COM port address supplied */ if(DebugMode.ComPortNumber == 0 && RTL::WideString::CompareWideStringInsensitive(DebugOption, L":0x", 3) == 0) { /* COM port address provided */ DebugOption += 3; while((*DebugOption >= '0' && *DebugOption <= '9') || (*DebugOption >= 'A' && *DebugOption <= 'F') || (*DebugOption >= 'a' && *DebugOption <= 'f')) { /* Get port address */ DebugMode.ComPortAddress *= 16; if(*DebugOption >= '0' && *DebugOption <= '9') { DebugMode.ComPortAddress += *DebugOption - '0'; } else if(*DebugOption >= 'A' && *DebugOption <= 'F') { DebugMode.ComPortAddress += *DebugOption - 'A' + 10; } else if(*DebugOption >= 'a' && *DebugOption <= 'f') { DebugMode.ComPortAddress += *DebugOption - 'a' + 10; } DebugOption++; } } /* Look for additional COM port parameters */ if(*DebugOption == ',') { /* Baud rate provided */ DebugOption++; while(*DebugOption >= '0' && *DebugOption <= '9') { /* Get baud rate */ DebugMode.ComPortBaudRate *= 10; DebugMode.ComPortBaudRate += *DebugOption - '0'; DebugOption++; } } } else if(RTL::WideString::CompareWideStringInsensitive(DebugOption, L"SCREEN", 6) == 0) { /* Enable framebuffer debugging mode */ DebugMode.Mode |= DEBUG_PROVIDER_FRAMEBUFFER; DebugOption += 6; } else if(*DebugOption == L';') { /* Skip separator */ DebugOption++; } else { /* Invalid debug option, skip it */ while(*DebugOption != L'\0' && *DebugOption != L' ' && *DebugOption != L';') { /* Advance debug option */ DebugOption++; } } } /* Ensure at least one debug port is enabled */ if(DebugMode.Mode != 0) { /* Enable debugging */ DebugMode.Enabled = TRUE; } /* Return success */ return STATUS_SUCCESS; } /** * Initializes the kernel's debugger I/O providers. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS KD::DebugIo::InitializeDebugIoProviders(VOID) { ULONG Index; XTSTATUS ProviderStatus, Status; /* Initialize debug I/O spinlock */ KE::SpinLock::InitializeSpinLock(&DebugIoLock); /* Initialize debug providers list */ RTL::LinkedList::InitializeListHead(&Providers); RTL::Memory::ZeroMemory(&DebugMode, sizeof(KD_DEBUG_MODE)); DetectDebugPorts(); /* Iterate over providers initialization routines */ for(Index = 0; Index < KDBG_PROVIDERS_COUNT; Index++) { /* Initialize provider */ ProviderStatus = IoProvidersInitRoutines[Index](); Status = (Status || ProviderStatus); } /* Initialize debug print routine */ SetPrintRoutine((PKD_PRINT_ROUTINE)DbgPrint); /* Return status code */ return Status; } /** * Initializes the framebuffer device provider for the kernel debugger. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS KD::DebugIo::InitializeFrameBufferProvider(VOID) { STATIC KD_DISPATCH_TABLE DispatchTable; ULONG Height, Width; /* Check if framebuffer provider is enabled */ if(DebugMode.Enabled && (DebugMode.Mode & DEBUG_PROVIDER_FRAMEBUFFER) == 0) { /* Screen is not enabled, no need to initialize provider */ return STATUS_PORT_DISCONNECTED; } /* Ensure frame buffer is initialized and get FB resolution */ HL::FrameBuffer::InitializeFrameBuffer(); HL::FrameBuffer::GetFrameBufferResolution(&Width, &Height); /* Print debug message */ DebugPrint(L"Initializing debug console at framebuffer device (%lu x %lu)\n", Width, Height); /* Initialize scroll region to full screen and white font color */ HL::FrameBuffer::InitializeScrollRegion(0, 0, Width - 1, Height - 1, 0xFFFFFFFF); /* Initialize screen dispatch table */ DispatchTable.PrintContext.WriteWideCharacter = HL::FrameBuffer::DisplayCharacter; RTL::LinkedList::InsertHeadList(&Providers, &DispatchTable.ListEntry); /* Return success */ return STATUS_SUCCESS; } /** * Initializes the serial port device provider for the kernel debugger. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTAPI XTSTATUS KD::DebugIo::InitializeSerialPortProvider(VOID) { STATIC KD_DISPATCH_TABLE DispatchTable; XTSTATUS Status; /* Check if serial port provider is enabled */ if(DebugMode.Enabled && (DebugMode.Mode & DEBUG_PROVIDER_COMPORT) == 0) { /* Serial port is not enabled, no need to initialize provider */ return STATUS_PORT_DISCONNECTED; } /* Check if custom COM port address supplied */ if(!DebugMode.ComPortAddress) { /* We support only a pre-defined number of ports */ if(DebugMode.ComPortNumber > COMPORT_COUNT) { /* Fail if wrong/unsupported port used */ return STATUS_INVALID_PARAMETER; } /* Check if serial port is set */ if(DebugMode.ComPortNumber == 0) { /* Use COM1 by default */ DebugMode.ComPortNumber = 1; } /* Set custom port address based on the port number and print debug message */ DebugMode.ComPortAddress = SerialPortList[DebugMode.ComPortNumber - 1]; DebugPrint(L"Initializing debug console at serial port (COM%lu, BaudRate: %lu)\n", DebugMode.ComPortNumber, DebugMode.ComPortBaudRate); } else { /* Custom port address supplied, print debug message */ DebugPrint(L"Initializing debug console at serial port (0x%lX, BaudRate: %lu)\n", DebugMode.ComPortAddress, DebugMode.ComPortBaudRate); } /* Initialize COM port */ Status = HL::ComPort::InitializeComPort(&SerialPort, (PUCHAR)UlongToPtr(DebugMode.ComPortAddress), DebugMode.ComPortBaudRate); if(Status != STATUS_SUCCESS) { /* Serial port initialization failed */ return Status; } /* Initialize serial port dispatch table */ DispatchTable.PrintContext.WriteWideCharacter = SerialWriteCharacter; RTL::LinkedList::InsertHeadList(&Providers, &DispatchTable.ListEntry); /* Return success */ return STATUS_SUCCESS; } /** * Configures the kernel's debug print routine by setting a new output handler. * * @param DebugPrintRoutine * Supplies a pointer to the new debug print routine. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KD::DebugIo::SetPrintRoutine(PKD_PRINT_ROUTINE DebugPrintRoutine) { /* Set debug print routine */ KdPrint = DebugPrintRoutine; } /** * Writes a character to the serial console. * * @param Character * The integer promotion of the character to be written. * * @return This routine returns a status code indicating the success or failure of the operation. * * @since XT 1.0 */ XTCDECL XTSTATUS KD::DebugIo::SerialWriteCharacter(WCHAR Character) { WCHAR Buffer[2]; /* Write character to the serial console */ Buffer[0] = Character; Buffer[1] = 0; return HL::ComPort::WriteComPort(&SerialPort, Buffer[0]); } ================================================ FILE: xtoskrnl/kd/exports.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/kd/exports.cc * DESCRIPTION: C-compatible API wrappers for exported kernel functions * DEVELOPERS: Aiken Harris */ #include /** * Prints a formatted string using the configured debug output providers. * * @param Format * Supplies the format string. * * @param ... * Supplies the variable argument list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTCDECL VOID DbgPrint(PCWSTR Format, ...) { VA_LIST Arguments; /* Initialise the va_list */ VA_START(Arguments, Format); KD::DebugIo::DbgPrint(Format, Arguments); /* Clean up the va_list */ VA_END(Arguments); } ================================================ FILE: xtoskrnl/ke/amd64/dispatch.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/amd64/dispatch.cc * DESCRIPTION: Kernel Thread Dispatcher * DEVELOPERS: Rafal Kupiec */ #include /** * Entry point for thread context switching. * * @param CurrentThread * Pointer to the KTHREAD structure of the current thread being suspended. * * @param RunLevel * Supplies the running level at which the wait was initiated. * * @return This routine returns TRUE if a kernel APC is pending and can be delivered, or FALSE otherwise. * * @since XT 1.0 */ XTFASTCALL BOOLEAN KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread, IN KRUNLEVEL RunLevel) { BOOLEAN PendingApc; /* Save non-volatile and XMM registers to the exception frame, align the stack and invoke the switch routine */ __asm__ volatile("subq %[ExFrameSize], %%rsp\n" "movq %%rbp, %c[ExRbp](%%rsp)\n" "movq %%rbx, %c[ExRbx](%%rsp)\n" "movq %%rdi, %c[ExRdi](%%rsp)\n" "movq %%rsi, %c[ExRsi](%%rsp)\n" "movq %%r12, %c[ExR12](%%rsp)\n" "movq %%r13, %c[ExR13](%%rsp)\n" "movq %%r14, %c[ExR14](%%rsp)\n" "movq %%r15, %c[ExR15](%%rsp)\n" "movdqa %%xmm6, %c[ExXmm6](%%rsp)\n" "movdqa %%xmm7, %c[ExXmm7](%%rsp)\n" "movdqa %%xmm8, %c[ExXmm8](%%rsp)\n" "movdqa %%xmm9, %c[ExXmm9](%%rsp)\n" "movdqa %%xmm10, %c[ExXmm10](%%rsp)\n" "movdqa %%xmm11, %c[ExXmm11](%%rsp)\n" "movdqa %%xmm12, %c[ExXmm12](%%rsp)\n" "movdqa %%xmm13, %c[ExXmm13](%%rsp)\n" "movdqa %%xmm14, %c[ExXmm14](%%rsp)\n" "movdqa %%xmm15, %c[ExXmm15](%%rsp)\n" "callq %P[SwitchRoutine]\n" "movq %c[ExRbp](%%rsp), %%rbp\n" "movq %c[ExRbx](%%rsp), %%rbx\n" "movq %c[ExRdi](%%rsp), %%rdi\n" "movq %c[ExRsi](%%rsp), %%rsi\n" "movq %c[ExR12](%%rsp), %%r12\n" "movq %c[ExR13](%%rsp), %%r13\n" "movq %c[ExR14](%%rsp), %%r14\n" "movq %c[ExR15](%%rsp), %%r15\n" "movdqa %c[ExXmm6](%%rsp), %%xmm6\n" "movdqa %c[ExXmm7](%%rsp), %%xmm7\n" "movdqa %c[ExXmm8](%%rsp), %%xmm8\n" "movdqa %c[ExXmm9](%%rsp), %%xmm9\n" "movdqa %c[ExXmm10](%%rsp), %%xmm10\n" "movdqa %c[ExXmm11](%%rsp), %%xmm11\n" "movdqa %c[ExXmm12](%%rsp), %%xmm12\n" "movdqa %c[ExXmm13](%%rsp), %%xmm13\n" "movdqa %c[ExXmm14](%%rsp), %%xmm14\n" "movdqa %c[ExXmm15](%%rsp), %%xmm15\n" "addq %[ExFrameSize], %%rsp\n" : "=a" (PendingApc) : "c" (CurrentThread), "d" (RunLevel), [ExFrameSize] "i" (sizeof(KEXCEPTION_FRAME) - 8), [ExR12] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R12)), [ExR13] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R13)), [ExR14] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R14)), [ExR15] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R15)), [ExRbp] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Rbp)), [ExRbx] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Rbx)), [ExRdi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Rdi)), [ExRsi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Rsi)), [ExXmm6] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm6)), [ExXmm7] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm7)), [ExXmm8] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm8)), [ExXmm9] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm9)), [ExXmm10] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm10)), [ExXmm11] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm11)), [ExXmm12] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm12)), [ExXmm13] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm13)), [ExXmm14] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm14)), [ExXmm15] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm15)), [SwitchRoutine] "i" (SwitchThreadStack) : "cc", "memory", "r8", "r9", "r10", "r11"); /* Return the APC status */ return PendingApc; } /** * Switches context from current thread to the new thread. * * @param CurrentThread * Pointer to the KTHREAD structure of the current thread being suspended. * * @param ApcBypass * Indicates whether the APC delivery should be bypassed. * * @return This routine returns TRUE if a kernel APC is pending and can be delivered, or FALSE otherwise. * * @since XT 1.0 */ XTFASTCALL BOOLEAN KE::Dispatcher::SwitchThreadContext(IN PKTHREAD CurrentThread, IN BOOLEAN ApcBypass) { UNIMPLEMENTED; return FALSE; } /** * Switches the thread stack and performs necessary operations to prepare for context switching. * * @param CurrentThread * Pointer to the KTHREAD structure of the current thread being suspended. * * @param RunLevel * Supplies the running level at which the wait was initiated. * * @return This routine returns TRUE if a kernel APC is pending and can be delivered, or FALSE otherwise. * * @since XT 1.0 */ XTFASTCALL BOOLEAN KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread, IN KRUNLEVEL RunLevel) { BOOLEAN PendingApc; /* Preserve MXCSR, synchronize with CPUs, switch stack and call the switch routine */ __asm__ volatile("pushq %%rbp\n" "subq %[FrameSize], %%rsp\n" "stmxcsr %c[SwMxCsr](%%rsp)\n" "movq %%gs:%c[PrcbcCurrentThread], %%r8\n" "BusyLoop:\n" "cmpb $0, %c[ThrdSwapBusy](%%r8)\n" "je ExitLoop\n" "pause\n" "jmp BusyLoop\n" "ExitLoop:\n" "movb %%dl, %c[SwApcBypass](%%rsp)\n" "movq %%rsp, %c[ThrdStack](%%rcx)\n" "movq %c[ThrdStack](%%r8), %%rsp\n" "movzbl %c[SwApcBypass](%%rsp), %%edx\n" "callq %P[SwitchRoutine]\n" "ldmxcsr %c[SwMxCsr](%%rsp)\n" "addq %[FrameSize], %%rsp\n" "popq %%rbp\n" : "=a" (PendingApc) : "c" (CurrentThread), "d" (RunLevel), [FrameSize] "i" (FIELD_OFFSET(KSWITCH_FRAME, Rbp)), [PrcbcCurrentThread] "i" (FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread)), [SwApcBypass] "i" (FIELD_OFFSET(KSWITCH_FRAME, ApcBypass)), [SwMxCsr] "i" (FIELD_OFFSET(KSWITCH_FRAME, MxCsr)), [SwitchRoutine] "i" (SwitchThreadContext), [ThrdStack] "i" (FIELD_OFFSET(KTHREAD, KernelStack)), [ThrdSwapBusy] "i" (FIELD_OFFSET(KTHREAD, SwapBusy)) : "cc", "memory", "r8", "r9", "r10", "r11"); /* Return the APC status */ return PendingApc; } ================================================ FILE: xtoskrnl/ke/amd64/krnlinit.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/amd64/krnlinit.cc * DESCRIPTION: CPU architecture specific kernel initialization * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Bootstraps an Application Processor (AP) into the active kernel. This routine is executed exclusively by secondary * processors after being awakened by the BSP. It is called directly from the startup trampoline. * * @param StartBlock * Supplies a pointer to the processor start block containing initialization information provided by the kernel. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KernelInit::BootstrapApplicationProcessor(IN PPROCESSOR_START_BLOCK StartBlock) { PKPROCESSOR_BLOCK ProcessorBlock; /* Initialize application CPU */ AR::ProcessorSupport::InitializeProcessor(StartBlock->ProcessorStructures); /* Initialize processor */ HL::Cpu::InitializeProcessor(); /* Raise to HIGH runlevel */ KE::RunLevel::RaiseRunLevel(HIGH_LEVEL); /* Mark processor as started */ StartBlock->Started = TRUE; /* Get current processor block */ ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); /* Enter infinite loop */ DebugPrint(L"KernelInit::BootstrapApplicationProcessor() finished for CPU #%lu. Entering infinite loop.\n", ProcessorBlock->CpuNumber); KE::Crash::HaltSystem(); } /** * Bootstraps the XT kernel and global subsystems. This routine is executed exclusively by the Bootstrap Processor * and it is called immediately after switching to the kernel boot stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KernelInit::BootstrapKernel(VOID) { PKPROCESSOR_CONTROL_BLOCK Prcb; ULONG_PTR PageDirectory[2]; PKPROCESS CurrentProcess; PKTHREAD CurrentThread; /* Get processor control block and current thread */ Prcb = KE::Processor::GetCurrentProcessorControlBlock(); CurrentThread = KE::Processor::GetCurrentThread(); /* Get current process */ CurrentProcess = CurrentThread->ApcState.Process; /* Initialize CPU power state structures */ PO::Idle::InitializeProcessorIdleState(Prcb); /* Save processor state */ KE::Processor::SaveProcessorState(&Prcb->ProcessorState); /* Initialize spin locks */ KE::SpinLock::InitializeAllLocks(); KE::SpinLock::InitializeLockQueues(); /* Lower to APC runlevel */ KE::RunLevel::LowerRunLevel(APC_LEVEL); /* Initialize XTOS kernel */ InitializeKernel(); /* Initialize Idle process */ PageDirectory[0] = 0; PageDirectory[1] = 0; KE::KProcess::InitializeProcess(CurrentProcess, 0, MAXULONG_PTR, PageDirectory, FALSE); CurrentProcess->Quantum = MAXCHAR; /* Initialize Idle thread */ KE::KThread::InitializeThread(CurrentProcess, CurrentThread, NULLPTR, NULLPTR, NULLPTR, NULLPTR, NULLPTR, AR::ProcessorSupport::GetBootStack(), TRUE); CurrentThread->NextProcessor = Prcb->CpuNumber; CurrentThread->Priority = THREAD_HIGH_PRIORITY; CurrentThread->State = Running; CurrentThread->Affinity = (ULONG_PTR)1 << Prcb->CpuNumber; CurrentThread->WaitRunLevel = DISPATCH_LEVEL; CurrentProcess->ActiveProcessors |= (ULONG_PTR)1 << Prcb->CpuNumber; /* Initialize Memory Manager */ MM::Manager::InitializeMemoryManager(); /* Enable shadow buffer for framebuffer */ HL::FrameBuffer::EnableShadowBuffer(); /* Start all application processors */ KE::Processor::InitializeProcessorBlocks(); HL::Cpu::StartAllProcessors(); /* Enter infinite loop */ DebugPrint(L"KernelInit::BootstrapKernel() finished. Entering infinite loop.\n"); KE::Crash::HaltSystem(); } /** * This routine initializes XT kernel. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KernelInit::InitializeKernel(VOID) { XTSTATUS Status; /* Initialize hardware layer subsystem */ Status = HL::Init::InitializeSystem(); if(Status != STATUS_SUCCESS) { /* Hardware layer initialization failed, kernel panic */ DebugPrint(L"Failed to initialize hardware layer subsystem!\n"); KE::Crash::Panic(0); } } /** * Performs architecture-specific initialization for the kernel executive. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KernelInit::InitializeMachine(VOID) { /* Re-enable IDE interrupts */ HL::IoPort::WritePort8(0x376, 0); HL::IoPort::WritePort8(0x3F6, 0); /* Initialize frame buffer */ HL::FrameBuffer::InitializeFrameBuffer(); /* Initialize page map support */ MM::Paging::InitializePageMapSupport(); /* Initialize Kernel Shared Data (KSD) */ KE::SharedData::InitializeKernelSharedData(); /* Initialize processor */ HL::Cpu::InitializeProcessor(); } /** * Switches execution to a new boot stack and transfers control to the KernelInit::StartKernel() routine. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KernelInit::SwitchBootStack(VOID) { ULONG_PTR Stack; PVOID StartKernel; /* Calculate the stack pointer at the top of the buffer, ensuring it is properly aligned as required by the ABI */ Stack = ((ULONG_PTR)AR::ProcessorSupport::GetBootStack() & ~(STACK_ALIGNMENT - 1)); /* Get address of KernelInit::StartKernel() */ StartKernel = (PVOID)KE::KernelInit::BootstrapKernel; /* Discard old stack frame, switch stack and jump to KernelInit::StartKernel() */ __asm__ volatile("movq %[Stack], %%rsp\n" "subq %[TotalSize], %%rsp\n" "xorq %%rbp, %%rbp\n" "jmp *%[TargetRoutine]\n" : : [Stack] "r" (Stack), [TargetRoutine] "r" (StartKernel), [TotalSize] "i" (FLOATING_SAVE_AREA_SIZE + KEXCEPTION_FRAME_SIZE + KSWITCH_FRAME_SIZE + KRETURN_ADDRESS_SIZE) : "memory", "rbp", "rsp"); } ================================================ FILE: xtoskrnl/ke/amd64/kthread.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/amd64/kthread.cc * DESCRIPTION: AMD64 thread manipulation support * DEVELOPERS: Rafal Kupiec */ #include /** * Initializes CPU architecture dependent context of a thread. * * @param Thread * Supplies a pointer to the thread being initialized. * * @param SystemRoutine * Supplies a pointer to the routine called during first scheduling. * * @param StartRoutine * Supplies a pointer to the routine called during thread startup. * * @param StartContext * Supplies a pointer to a context data that will be passed to start routine. * * @param ContextRecord * Supplies a pointer to a context record which stores the initial state of the user mode thread. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KThread::InitializeThreadContext(IN PKTHREAD Thread, IN PKSYSTEM_ROUTINE SystemRoutine, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext, IN PCONTEXT ContextRecord) { PKTHREAD_INIT_FRAME ThreadFrame; /* Set initial thread frame */ ThreadFrame = ((PKTHREAD_INIT_FRAME)Thread->InitialStack) - 1; /* Fill floating point save area with zeroes */ RTL::Memory::ZeroMemory(&ThreadFrame->NpxFrame, sizeof(FLOATING_SAVE_AREA)); /* Check if context provided for this thread */ if(ContextRecord) { /* User mode thread needs further initialization, this is not completed */ UNIMPLEMENTED; /* Fill exception and trap frames with zeroes */ RTL::Memory::ZeroMemory(&ThreadFrame->ExceptionFrame, sizeof(KEXCEPTION_FRAME)); RTL::Memory::ZeroMemory(&ThreadFrame->TrapFrame, sizeof(KTRAP_FRAME)); /* Disable debug registers and enable context registers */ ContextRecord->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS | CONTEXT_CONTROL; /* Align the stack and reserve space for 4 parameters and return value */ ContextRecord->Rsp = (ContextRecord->Rsp & ~15) - 40; /* Set CS and SS segments for user mode */ ContextRecord->SegCs = KGDT_R3_CODE | RPL_MASK; ContextRecord->SegSs = KGDT_R3_DATA | RPL_MASK; /* This is user mode thread */ Thread->PreviousMode = UserMode; /* Enable floating point state */ Thread->NpxState = NPX_STATE_SCRUB; /* Set initial floating point state */ ThreadFrame->NpxFrame.ControlWord = 0x27F; ThreadFrame->NpxFrame.TagWord = 0xFFFF; /* Clear DR6 and DR7 registers */ ThreadFrame->TrapFrame.Dr6 = 0; ThreadFrame->TrapFrame.Dr7 = 0; /* Set initial MXCSR register value */ ThreadFrame->TrapFrame.MxCsr = INITIAL_MXCSR; /* Initialize exception frame */ ThreadFrame->ExceptionFrame.P1Home = (ULONG64)StartContext; ThreadFrame->ExceptionFrame.P2Home = (ULONG64)StartRoutine; ThreadFrame->ExceptionFrame.P3Home = (ULONG64)SystemRoutine; ThreadFrame->ExceptionFrame.P4Home = (ULONG64)SystemRoutine; } else { /* This is kernel mode thread */ Thread->PreviousMode = KernelMode; /* Disable floating point state */ Thread->NpxState = NPX_STATE_UNUSED; /* Set thread start address */ ThreadFrame->StartFrame.Return = (ULONG64)NULLPTR; } /* Initialize thread startup information */ ThreadFrame->StartFrame.P1Home = (ULONG64)StartContext; ThreadFrame->StartFrame.P2Home = (ULONG64)StartRoutine; ThreadFrame->StartFrame.P3Home = (ULONG64)SystemRoutine; ThreadFrame->StartFrame.P4Home = (ULONG64)SystemRoutine; /* Initialize switch frame */ ThreadFrame->SwitchFrame.ApcBypass = APC_LEVEL; ThreadFrame->SwitchFrame.MxCsr = INITIAL_MXCSR; ThreadFrame->SwitchFrame.Rbp = (ULONG64)&ThreadFrame->TrapFrame; /* Set thread stack */ Thread->KernelStack = &ThreadFrame->SwitchFrame; } ================================================ FILE: xtoskrnl/ke/amd64/proc.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/amd64/proc.cc * DESCRIPTION: AMD64 processor-related functionality for the kernel * DEVELOPERS: Rafal Kupiec */ #include /** * Gets the processor block for the currently executing processor. * * @return This routine returns the current processor block read from the GS register. * * @since XT 1.0 */ XTAPI PKPROCESSOR_BLOCK KE::Processor::GetCurrentProcessorBlock(VOID) { /* Get processor block from GS register */ return (PKPROCESSOR_BLOCK)AR::CpuFunctions::ReadGSQuadWord(FIELD_OFFSET(KPROCESSOR_BLOCK, Self)); } /** * Gets the processor control block for the currently executing processor. * * @return This routine returns the current processor control block read from the GS register. * * @since XT 1.0 */ XTAPI PKPROCESSOR_CONTROL_BLOCK KE::Processor::GetCurrentProcessorControlBlock(VOID) { return (PKPROCESSOR_CONTROL_BLOCK)AR::CpuFunctions::ReadGSQuadWord(FIELD_OFFSET(KPROCESSOR_BLOCK, CurrentPrcb)); } /** * Gets the number of the currently executing processor. * * @return This routine returns the zero-indexed processor number. * * @since XT 1.0 */ XTAPI ULONG KE::Processor::GetCurrentProcessorNumber(VOID) { return (ULONG)AR::CpuFunctions::ReadGSQuadWord(FIELD_OFFSET(KPROCESSOR_BLOCK, CpuNumber)); } /** * Gets the current thread running on the currently executing processor. * * @return This routine returns the address of the current thread object. * * @since NT 3.5 */ XTAPI PKTHREAD KE::Processor::GetCurrentThread(VOID) { return (PKTHREAD)AR::CpuFunctions::ReadGSQuadWord(FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread)); } /** * Gets the processor block for the specified processor number. * * @param CpuNumber * Supplies the zero-indexed processor number. * * @return This routine returns a pointer to the processor block, or NULLPTR if invalid. * * @since XT 1.0 */ XTAPI PKPROCESSOR_BLOCK KE::Processor::GetProcessorBlock(IN ULONG CpuNumber) { /* Check if the requested CPU number is within dynamic bounds */ if(CpuNumber >= InstalledCpus || ProcessorBlocks == NULLPTR || ProcessorBlocks[CpuNumber] == NULLPTR) { /* Invalid CPU number, return NULLPTR */ return NULLPTR; } /* Return requested processor block */ return ProcessorBlocks[CpuNumber]; } /** * Initializes the global processor structures by allocating an array of processor block pointers. * * @return This routine returns a status code indicating the success or failure of the allocation. * * @since XT 1.0 */ XTAPI XTSTATUS KE::Processor::InitializeProcessorBlocks() { PACPI_SYSTEM_INFO SystemInfo; XTSTATUS Status; /* Save number of CPUs installed */ HL::Acpi::GetSystemInformation(&SystemInfo); InstalledCpus = SystemInfo->CpuCount; /* Allocate an array of pointers */ Status = MM::Allocator::AllocatePool(NonPagedPool, InstalledCpus * sizeof(PKPROCESSOR_BLOCK), (PVOID*)&ProcessorBlocks); if(Status != STATUS_SUCCESS) { /* Failed to allocate memory, return error */ return Status; } /* Zero the array initially */ RTL::Memory::ZeroMemory(ProcessorBlocks, InstalledCpus * sizeof(PKPROCESSOR_BLOCK)); /* Return success */ return STATUS_SUCCESS; } /** * Registers the hardware APIC ID for the currently executing processor. * * @param ApicId * Supplies the hardware APIC ID to register in the processor block. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::Processor::RegisterHardwareId(IN ULONG HardwareId) { PKPROCESSOR_BLOCK CurrentBlock; /* Retrieve the processor block for the executing core */ CurrentBlock = GetCurrentProcessorBlock(); if(CurrentBlock != NULLPTR) { /* Register the hardware identifier for IPI targeting */ CurrentBlock->HardwareId = HardwareId; } } /** * Registers or deregisters a processor block in the global CPU table. * * @param CpuNumber * Specifies the logical processor number. * * @param ProcessorBlock * Supplies a pointer to the processor block. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::Processor::RegisterProcessorBlock(ULONG CpuNumber, PKPROCESSOR_BLOCK ProcessorBlock) { /* Check if the requested CPU number is within dynamic bounds */ if(ProcessorBlocks != NULLPTR && CpuNumber < InstalledCpus) { /* Register processor block */ ProcessorBlocks[CpuNumber] = ProcessorBlock; } } /** * Saves the current processor state. * * @param State * Supplies a pointer to the processor state structure. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::Processor::SaveProcessorState(OUT PKPROCESSOR_STATE CpuState) { /* Save CR registers */ CpuState->SpecialRegisters.Cr0 = AR::CpuFunctions::ReadControlRegister(0); CpuState->SpecialRegisters.Cr2 = AR::CpuFunctions::ReadControlRegister(2); CpuState->SpecialRegisters.Cr3 = AR::CpuFunctions::ReadControlRegister(3); CpuState->SpecialRegisters.Cr4 = AR::CpuFunctions::ReadControlRegister(4); CpuState->SpecialRegisters.Cr8 = AR::CpuFunctions::ReadControlRegister(8); /* Save DR registers */ CpuState->SpecialRegisters.KernelDr0 = AR::CpuFunctions::ReadDebugRegister(0); CpuState->SpecialRegisters.KernelDr1 = AR::CpuFunctions::ReadDebugRegister(1); CpuState->SpecialRegisters.KernelDr2 = AR::CpuFunctions::ReadDebugRegister(2); CpuState->SpecialRegisters.KernelDr3 = AR::CpuFunctions::ReadDebugRegister(3); CpuState->SpecialRegisters.KernelDr6 = AR::CpuFunctions::ReadDebugRegister(6); CpuState->SpecialRegisters.KernelDr7 = AR::CpuFunctions::ReadDebugRegister(7); /* Save MSR registers */ CpuState->SpecialRegisters.MsrGsBase = AR::CpuFunctions::ReadModelSpecificRegister(X86_MSR_GSBASE); CpuState->SpecialRegisters.MsrGsSwap = AR::CpuFunctions::ReadModelSpecificRegister(X86_MSR_KERNEL_GSBASE); CpuState->SpecialRegisters.MsrCStar = AR::CpuFunctions::ReadModelSpecificRegister(X86_MSR_CSTAR); CpuState->SpecialRegisters.MsrLStar = AR::CpuFunctions::ReadModelSpecificRegister(X86_MSR_LSTAR); CpuState->SpecialRegisters.MsrStar = AR::CpuFunctions::ReadModelSpecificRegister(X86_MSR_STAR); CpuState->SpecialRegisters.MsrSyscallMask = AR::CpuFunctions::ReadModelSpecificRegister(X86_MSR_FMASK); /* Save XMM control/status register */ CpuState->SpecialRegisters.MxCsr = AR::CpuFunctions::ReadMxCsrRegister(); /* Save GDT, IDT, LDT and TaskRegister */ AR::CpuFunctions::StoreGlobalDescriptorTable(&CpuState->SpecialRegisters.Gdtr.Limit); AR::CpuFunctions::StoreInterruptDescriptorTable(&CpuState->SpecialRegisters.Idtr.Limit); AR::CpuFunctions::StoreLocalDescriptorTable(&CpuState->SpecialRegisters.Ldtr); AR::CpuFunctions::StoreTaskRegister(&CpuState->SpecialRegisters.Tr); } ================================================ FILE: xtoskrnl/ke/apc.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/apc.cc * DESCRIPTION: Kernel APC objects support * DEVELOPERS: Rafal Kupiec */ #include /** * Initializes an APC object. * * @param Apc * Supplies a pointer to the APC object. * * @param Thread * Supplies a pointer to the thread object. * * @param Environment * Specifies an environment in which the APC will run. * * @param KernelRoutine * Supplies a pointer to routine called at APC_LEVEL. * * @param RundownRoutine * Supplies a pointer to routine called on thread exit. * * @param NormalRoutine * Supplies a pointer to routine called at IRQL 0. * * @param ApcMode * Specifies processor mode, in which NormalRoutine gets called. * * @param Context * Supplies a pointer to memory area containing data passed to NormalRoutine. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID KE::Apc::InitializeApc(IN PKAPC Apc, IN PKTHREAD Thread, IN KAPC_ENVIRONMENT Environment, IN PKKERNEL_ROUTINE KernelRoutine, IN PKRUNDOWN_ROUTINE RundownRoutine, IN PKNORMAL_ROUTINE NormalRoutine, IN KPROCESSOR_MODE ApcMode, IN PVOID Context) { /* Set APC type and thread */ Apc->Type = ApcObject; Apc->Thread = Thread; /* Set routines */ Apc->KernelRoutine = KernelRoutine; Apc->RundownRoutine = RundownRoutine; Apc->NormalRoutine = NormalRoutine; /* Check target environment */ if(Environment == CurrentApcEnvironment) { /* Use current APC environment taken from thread */ Apc->ApcStateIndex = Thread->ApcStateIndex; } else { /* Use new APC environment */ Apc->ApcStateIndex = Environment; } /* Check if normal routine specified */ if(NormalRoutine) { /* Set context and mode for notmal APC */ Apc->ApcMode = ApcMode; Apc->NormalContext = Context; } else { /* Set context and mode for special APC */ Apc->ApcMode = KernelMode; Apc->NormalContext = NULLPTR; } /* Mark APC as not inserted yet */ Apc->Inserted = FALSE; } ================================================ FILE: xtoskrnl/ke/bootinfo.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/bootinfo.cc * DESCRIPTION: Bootloader-provided system information handling support * DEVELOPERS: Aiken Harris */ #include /** * Retrieves a pointer to the DebugPrint routine provided by the bootloader. * * @return This routine returns a pointer to the DebugPrint routine. * * @since XT 1.0 */ XTAPI PKD_PRINT_ROUTINE KE::BootInformation::GetDebugPrint(VOID) { return (PKD_PRINT_ROUTINE)InitializationBlock->LoaderInformation.DbgPrint; } /** * Retrieves the system firmware type (BIOS or UEFI). * * @return This routine returns the type of the system firmware. * * @since XT 1.0 */ XTAPI SYSTEM_FIRMWARE_TYPE KE::BootInformation::GetFirmwareType(VOID) { return InitializationBlock->FirmwareInformation.FirmwareType; } /** * Retrieves a pointer to the specified kernel parameter within the kernel parameters list. * * @param ParameterName * Supplies a pointer to a null-terminated wide string specifying the name of the parameter to search for. * * @param Parameter * Supplies a pointer to a variable that receives a pointer to the matching parameter, or NULLPTR if not found. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS KE::BootInformation::GetKernelParameter(IN PCWSTR ParameterName, OUT PCWSTR *Parameter) { PCWSTR Match, SearchStart; SIZE_T ParameterNameLength; /* Validate input parameters */ if(!ParameterName || !Parameter) { /* Invalid input parameters, return error */ return STATUS_INVALID_PARAMETER; } /* Get the length of the parameter name we are looking for */ ParameterNameLength = RTL::WideString::WideStringLength(ParameterName, 0); if(ParameterNameLength == 0) { /* Do not allow empty parameter names */ return STATUS_INVALID_PARAMETER; } /* Assume the requested parameter is not present in the kernel parameters */ *Parameter = NULLPTR; /* Start searching from the beginning of the list */ SearchStart = InitializationBlock->KernelParameters; /* Search for the parameter name */ while((Match = RTL::WideString::FindWideStringInsensitive(SearchStart, ParameterName))) { /* Check if the match is at the start of the string or preceded by a space */ if(Match == InitializationBlock->KernelParameters || *(Match - 1) == L' ') { /* Check the character after the match to avoid matching prefixes */ if(Match[ParameterNameLength] == L'\0' || Match[ParameterNameLength] == L' ' || Match[ParameterNameLength] == L'=') { /* A valid parameter was found, return a pointer to it */ *Parameter = Match; return STATUS_SUCCESS; } } /* The match was a substring of a larger token, continue searching */ SearchStart = Match + 1; } /* Parameter not found */ return STATUS_NOT_FOUND; } /** * Retrieves the value of a specified kernel parameter and copies it into a buffer. * * @param ParameterName * Supplies a pointer to a null-terminated wide string specifying the name of the parameter to search for. * * @param ValueBuffer * Supplies a pointer to a variable that receives the null-terminated value of the matching parameter. * * @param BufferSize * Supplies the size of the value buffer, in wide characters. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS KE::BootInformation::GetKernelParameterValue(IN PCWSTR ParameterName, OUT PWSTR ValueBuffer, IN SIZE_T BufferSize) { PCWSTR Match; SIZE_T NameLength, Index; XTSTATUS Status; /* Validate input parameters */ if(!ParameterName || !ValueBuffer || BufferSize == 0) { /* Invalid input parameters, return error */ return STATUS_INVALID_PARAMETER; } /* Initialize the output buffer to an empty string */ ValueBuffer[0] = L'\0'; /* Find the parameter in the list using the base function */ Status = GetKernelParameter(ParameterName, &Match); if(Status != STATUS_SUCCESS) { /* Parameter not found, return error */ return Status; } /* Move pointer past the parameter name */ NameLength = RTL::WideString::WideStringLength(ParameterName, 0); Match += NameLength; /* If the parameter has a value (indicated by '='), copy it */ if(*Match == L'=') { /* Skip the assignment operator */ Match++; /* Copy the value to the caller's buffer until a space or end of string is reached */ Index = 0; while(*Match != L'\0' && *Match != L' ' && Index < (BufferSize - 1)) { /* Copy the character */ ValueBuffer[Index] = *Match; Index++; Match++; } /* Null-terminate the isolated value string */ ValueBuffer[Index] = L'\0'; } /* Value successfully retrieved (or parameter exists without value) */ return STATUS_SUCCESS; } /** * Retrieves a pointer to the list of memory descriptors. * * @return This routine returns a pointer to the list of memory descriptors. * * @since XT 1.0 */ XTAPI PLIST_ENTRY KE::BootInformation::GetMemoryDescriptors(VOID) { return &InitializationBlock->MemoryDescriptorListHead; } /** * Retrieves a pointer to the list of system resources. * * @return This routine returns a pointer to the list of system resources. * * @since XT 1.0 */ XTAPI PLIST_ENTRY KE::BootInformation::GetSystemResources(VOID) { return &InitializationBlock->SystemResourcesListHead; } /** * Initializes the bootloader-provided system information. * * @param Block * Supplies a pointer to the kernel initialization block. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::BootInformation::InitializeInitializationBlock(IN PKERNEL_INITIALIZATION_BLOCK Block) { /* Check if the initialization block is already initialized */ if(!InitializationBlock) { /* Save the kernel initialization block */ InitializationBlock = Block; } } ================================================ FILE: xtoskrnl/ke/crash.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/panic.cc * DESCRIPTION: System shutdown and kernel panic mechanism * DEVELOPERS: Rafal Kupiec */ #include /** * Halts the system. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::Crash::HaltSystem(VOID) { /* Enter infinite loop */ for(;;) { /* Halt system */ AR::CpuFunctions::ClearInterruptFlag(); AR::CpuFunctions::Halt(); } } /** * Crashes the system upon detecting a fatal error in which either it is unable to recover or continue to run system. * * @param Code * Specifies the reason for the kernel panic. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::Crash::Panic(IN ULONG Code) { Panic(Code, 0, 0, 0, 0); } /** * Crashes the system upon detecting a fatal error in which either it is unable to recover or continue to run system. * * @param Code * Specifies the reason for the kernel panic. * * @param Parameter1 * Supplies additional information about the kernel panic. * * @param Parameter2 * Supplies additional information about the kernel panic. * * @param Parameter3 * Supplies additional information about the kernel panic. * * @param Parameter4 * Supplies additional information about the kernel panic. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::Crash::Panic(IN ULONG Code, IN ULONG_PTR Parameter1, IN ULONG_PTR Parameter2, IN ULONG_PTR Parameter3, IN ULONG_PTR Parameter4) { KD::DebugIo::KdPrint(L"Fatal System Error: 0x%08lx (0x%zx 0x%zx 0x%zx 0x%zx)\nKernel Panic!\n\n", Code, Parameter1, Parameter2, Parameter3, Parameter4); HaltSystem(); } ================================================ FILE: xtoskrnl/ke/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/data.cc * DESCRIPTION: Kernel Library global and static data * DEVELOPERS: Aiken Harris */ #include /* Kernel initialization block passed by boot loader */ PKERNEL_INITIALIZATION_BLOCK KE::BootInformation::InitializationBlock = {}; /* Kernel initial process */ EPROCESS KE::KProcess::InitialProcess; /* Kernel initial thread */ ETHREAD KE::KThread::InitialThread = {}; /* Kernel UBSAN active frame flag */ BOOLEAN KE::KUbsan::ActiveFrame = FALSE; /* Total number of installed processors in the system */ ULONG KE::Processor::InstalledCpus; /* Array of pointers to processor control blocks */ PKPROCESSOR_BLOCK *KE::Processor::ProcessorBlocks; /* Kernel shared data (KSD) */ PKSHARED_DATA KE::SharedData::KernelSharedData; /* Kernel dispatcher lock queue */ KSPIN_LOCK KE::SpinLock::DispatcherLockQueue; /* Kernel expansion lock queue */ KSPIN_LOCK KE::SpinLock::ExpansionLockQueue; /* Kernel file system structures lock queue */ KSPIN_LOCK KE::SpinLock::FileSystemLockQueue; /* Kernel IO cancel lock queue */ KSPIN_LOCK KE::SpinLock::IoCancelLockQueue; /* Kernel IO completion lock queue */ KSPIN_LOCK KE::SpinLock::IoCompletionLockQueue; /* Kernel IO database lock queue */ KSPIN_LOCK KE::SpinLock::IoDatabaseLockQueue; /* Kernel IO VPB lock queue */ KSPIN_LOCK KE::SpinLock::IoVpbLockQueue; /* Kernel cache master lock queue */ KSPIN_LOCK KE::SpinLock::MasterLockQueue; /* Kernel non-paged allocator lock queue */ KSPIN_LOCK KE::SpinLock::NonPagedAllocLockQueue; /* Kernel non-paged pool lock queue */ KSPIN_LOCK KE::SpinLock::NonPagedPoolLockQueue; /* Kernel PFN lock queue */ KSPIN_LOCK KE::SpinLock::PfnLockQueue; /* Kernel system space lock queue */ KSPIN_LOCK KE::SpinLock::SystemSpaceLockQueue; /* Kernel Timer table lock queue */ KSPIN_LOCK KE::SpinLock::TimerTableLockQueue; /* Kernel VACB lock queue */ KSPIN_LOCK KE::SpinLock::VacbLockQueue; /* Kernel work queue lock queue */ KSPIN_LOCK KE::SpinLock::WorkLockQueue; /* Kernel boot resources list */ LIST_ENTRY KE::SystemResources::ResourcesListHead; /* Kernel boot resources lock */ KSPIN_LOCK KE::SystemResources::ResourcesLock; /* Kernel boot time */ LARGE_INTEGER KE::SystemTime::BootTime; /* The maximum interval between system clock interrupts */ ULONG KE::SystemTime::MaximumIncrement; /* The minimum interval between system clock interrupts */ ULONG KE::SystemTime::MinimumIncrement; /* Accumulator tracking fractional ticks, decremented until a full tick elapses */ LONG KE::SystemTime::TickOffset; /* The runtime adjustment value applied to the system clock at each interrupt */ ULONG KE::SystemTime::TimeAdjustment; ================================================ FILE: xtoskrnl/ke/dispatch.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/dispatch.cc * DESCRIPTION: Kernel Thread Dispatcher * DEVELOPERS: Rafal Kupiec */ #include /** * Exits the dispatcher, switches context to a new thread and lowers runlevel to its original state. * * @param OldRunLevel * Supplies the original runlevel state. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID KE::Dispatcher::ExitDispatcher(IN KRUNLEVEL OldRunLevel) { UNIMPLEMENTED; /* Lower runlevel */ RunLevel::LowerRunLevel(OldRunLevel); } /** * Updates the runtime quantum of the currently executing thread and handles preemption. * * @param TrapFrame * Supplies a pointer to the hardware trap frame representing the interrupted execution context. * * @param RunLevel * Supplies the system run level at which the interrupt was taken. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::Dispatcher::UpdateRunTime(IN PKTRAP_FRAME TrapFrame, IN KRUNLEVEL RunLevel) { } ================================================ FILE: xtoskrnl/ke/dpc.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/dpc.cc * DESCRIPTION: Deferred Procedure Call (DPC) support * DEVELOPERS: Rafal Kupiec */ #include /** * Initializes Deferred Procedure Call (DPC) object. * * @param Dpc * Supplies a pointer to the DPC being initialized. * * @param DpcRoutine * Supplies a pointer to the DPC routine being called on object removal. * * @param DpcContext * Supplies a pointer to memory area containing context data for DPC routine. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID KE::Dpc::InitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DpcRoutine, IN PVOID DpcContext) { /* Initialize DPC */ Dpc->Type = DpcObject; Dpc->Number = 0; Dpc->Importance = MediumImportance; /* Initialize DPC routine and context data */ Dpc->DeferredContext = DpcContext; Dpc->DeferredRoutine = DpcRoutine; Dpc->DpcData = NULLPTR; } /** * Initializes Deferred Procedure Call (DPC) object. * * @param Dpc * Supplies a pointer to the DPC being initialized. * * @param DpcRoutine * Supplies a pointer to the DPC routine being called on object removal. * * @param DpcContext * Supplies a pointer to memory area containing context data for DPC routine. * * @return This routine does not return any value. * * @since NT 5.2 */ XTAPI VOID KE::Dpc::InitializeThreadedDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DpcRoutine, IN PVOID DpcContext) { /* Initialize threaded DPC */ Dpc->Type = ThreadedDpcObject; Dpc->Number = 0; Dpc->Importance = MediumImportance; /* Initialize DPC routine and context data */ Dpc->DeferredContext = DpcContext; Dpc->DeferredRoutine = DpcRoutine; Dpc->DpcData = NULLPTR; } /** * Sets the target processor number for DPC. * * @param Dpc * Supplies a pointer to the DPC object. * * @param Number * Supplies the target processor number. * * @return This routine does not return any value. * * @since NT 4.0 */ XTAPI VOID KE::Dpc::SetTargetProcessor(IN PKDPC Dpc, IN CCHAR Number) { Dpc->Number = MAXIMUM_PROCESSORS + Number; } /** * Decrements the DPC call barier. * * @param SystemArgument * Supplies an address of the DPC call barrier. * * @return This routine does not return any value. * * @since NT 5.2 */ XTAPI VOID KE::Dpc::SignalCallDone(IN PVOID SystemArgument) { RTL::Atomic::Decrement32((PLONG)SystemArgument); } /** * Decrements the DPC call reverse barier. * * @param SystemArgument * Supplies an address of the DPC call barrier. * * @return This routine returns TRUE if just one processor is waiting on the barrier, FALSE if more. * * @since NT 5.2 */ XTAPI BOOLEAN KE::Dpc::SignalCallSynchronize(IN PVOID SystemArgument) { UNIMPLEMENTED; /* SMP not yet implemented, return TRUE */ return TRUE; } /** * Retires the expired DPC objects found in the DPC list. * * @param Prcb * Supplies apointer to the Prcessor Control Block (PRCB). * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID KE::Dpc::RetireList(IN PKPROCESSOR_CONTROL_BLOCK Prcb) { UNIMPLEMENTED; } ================================================ FILE: xtoskrnl/ke/event.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/event.cc * DESCRIPTION: Kernel events support * DEVELOPERS: Rafal Kupiec */ #include /** * Clears the signal state of the event. * * @param Event * Supplies a pointer to the event object. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID KE::Event::ClearEvent(IN PKEVENT Event) { /* Clear event's signal state */ Event->Header.SignalState = FALSE; } /** * Initializes a kernel event. * * @param Event * Supplies a pointer to the event object. * * @param EventType * Specifies an event type. * * @param InitialState * Specifies the initial signal state of the event. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID KE::Event::InitializeEvent(OUT PKEVENT Event, IN KEVENT_TYPE EventType, IN BOOLEAN InitialState) { /* Initialize event dispatcher header */ Event->Header.Type = EventType; Event->Header.SignalState = InitialState; /* Initialize event wait list */ RtlInitializeListHead(&Event->Header.WaitListHead); } /** * Sets new signal state and satisfy waits if possible. * * @param Event * Supplies a pointer to the event object. * * @param Increment * Specifies an event priority boost value. * * @param Wait * Specifies whether to call kernel wait routines or not. * * @return This routine returns the previous signal state of the event. * * @since NT 3.5 */ XTAPI LONG KE::Event::SetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait) { UNIMPLEMENTED; return 0; } ================================================ FILE: xtoskrnl/ke/exports.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/exports.cc * DESCRIPTION: C-compatible API wrappers for exported kernel functions * DEVELOPERS: Aiken Harris */ #include /** * Acquires a specified queued spinlock. * * @param LockLevel * Supplies the queued spinlock level. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTFASTCALL VOID KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_LEVEL LockLevel) { KE::SpinLock::AcquireQueuedSpinLock(LockLevel); } /** * Acquires a kernel spin lock. * * @param SpinLock * Supplies a pointer to the kernel spin lock. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTFASTCALL VOID KeAcquireSpinLock(IN OUT PKSPIN_LOCK SpinLock) { KE::SpinLock::AcquireSpinLock(SpinLock); } /** * Looks for an unacquired system resource of the specified type and acquires it. * * @param ResourceType * Supplies system resource type. * * @param ResourceHeader * Specifies a memory area where a pointer to the system resource header will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCLINK XTAPI XTSTATUS KeAcquireSystemResource(IN SYSTEM_RESOURCE_TYPE ResourceType, OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader) { return KE::SystemResources::AcquireResource(ResourceType, ResourceHeader); } /** * Cancels the timer. * * @param Timer * Supplies a pointer to a timer object. * * @return This routine returns TRUE if the cancelled timer was set, or FALSE otherwise. * * @since NT 3.5 */ XTCLINK XTAPI BOOLEAN KeCancelTimer(IN PKTIMER Timer) { return KE::Timer::CancelTimer(Timer); } /** * Gets the current running level of the current processor. * * @return This routine returns the current running level. * * @since XT 1.0 */ XTCLINK XTFASTCALL KRUNLEVEL KeGetCurrentRunLevel(VOID) { return KE::RunLevel::GetCurrentRunLevel(); } /** * Looks for an unacquired system resource of the specified type and returns it without acquiring an ownership. * * @param ResourceType * Supplies system resource type. * * @param ResourceHeader * Specifies a memory area where a pointer to the system resource header will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCLINK XTAPI XTSTATUS KeGetSystemResource(IN SYSTEM_RESOURCE_TYPE ResourceType, OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader) { return KE::SystemResources::GetResource(ResourceType, ResourceHeader); } /** * Reads the current signal state of the given timer. * * @param Timer * Supplies a pointer to a timer object. * * @return This routine returns TRUE if the timer is set, or FALSE otherwise. * * @since XT 1.0 */ XTCLINK XTAPI BOOLEAN KeGetTimerState(IN PKTIMER Timer) { return KE::Timer::GetState(Timer); } /** * Initializes an APC object. * * @param Apc * Supplies a pointer to the APC object. * * @param Thread * Supplies a pointer to the thread object. * * @param Environment * Specifies an environment in which the APC will run. * * @param KernelRoutine * Supplies a pointer to routine called at APC_LEVEL. * * @param RundownRoutine * Supplies a pointer to routine called on thread exit. * * @param NormalRoutine * Supplies a pointer to routine called at IRQL 0. * * @param ApcMode * Specifies processor mode, in which NormalRoutine gets called. * * @param Context * Supplies a pointer to memory area containing data passed to NormalRoutine. * * @return This routine does not return any value. * * @since NT 3.5 */ XTCLINK XTAPI VOID KeInitializeApc(IN PKAPC Apc, IN PKTHREAD Thread, IN KAPC_ENVIRONMENT Environment, IN PKKERNEL_ROUTINE KernelRoutine, IN PKRUNDOWN_ROUTINE RundownRoutine, IN PKNORMAL_ROUTINE NormalRoutine, IN KPROCESSOR_MODE ApcMode, IN PVOID Context) { KE::Apc::InitializeApc(Apc, Thread, Environment, KernelRoutine, RundownRoutine, NormalRoutine, ApcMode, Context); } /** * Initializes Deferred Procedure Call (DPC) object. * * @param Dpc * Supplies a pointer to the DPC being initialized. * * @param DpcRoutine * Supplies a pointer to the DPC routine being called on object removal. * * @param DpcContext * Supplies a pointer to memory area containing context data for DPC routine. * * @return This routine does not return any value. * * @since NT 3.5 */ XTCLINK XTAPI VOID KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DpcRoutine, IN PVOID DpcContext) { KE::Dpc::InitializeDpc(Dpc, DpcRoutine, DpcContext); } /** * Initializes Deferred Procedure Call (DPC) object. * * @param Dpc * Supplies a pointer to the DPC being initialized. * * @param DpcRoutine * Supplies a pointer to the DPC routine being called on object removal. * * @param DpcContext * Supplies a pointer to memory area containing context data for DPC routine. * * @return This routine does not return any value. * * @since NT 5.2 */ XTCLINK XTAPI VOID KeInitializeThreadedDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DpcRoutine, IN PVOID DpcContext) { KE::Dpc::InitializeThreadedDpc(Dpc, DpcRoutine, DpcContext); } /** * Initializes an extended kernel timer. * * @param Timer * Supplies a pointer to a timer object. * * @param Type * Supplies the type of the timer. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID KeInitializeTimer(OUT PKTIMER Timer, IN KTIMER_TYPE Type) { KE::Timer::InitializeTimer(Timer, Type); } /** * Initializes a kernel semaphore object. * * @param Semaphore * Supplies a pointer to a semaphore object. * * @param Count * Specifies the initial count value of the semaphore. * * @param Limit * Specifies a maximum count value of the semaphore. * * @return This routine does not return any value. * * @since NT 3.5 */ XTCLINK XTAPI VOID KeInitializeSemaphore(IN PKSEMAPHORE Semaphore, IN LONG Count, IN LONG Limit) { KE::Semaphore::InitializeSemaphore(Semaphore, Count, Limit); } /** * Initializes a kernel spinlock object. * * @param SpinLock * Supplies a pointer to a kernel spin lock. * * @return This routine does not return any value. * * @since NT 3.5 */ XTCLINK XTAPI VOID KeInitializeSpinLock(IN PKSPIN_LOCK SpinLock) { KE::SpinLock::InitializeSpinLock(SpinLock); } /** * Lowers the running level of the current processor. * * @param RunLevel * Supplies the new running level to lower to. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTFASTCALL VOID KeLowerRunLevel(KRUNLEVEL RunLevel) { KE::RunLevel::LowerRunLevel(RunLevel); } /** * Raises the running level of the current processor. * * @param RunLevel * Supplies the new running level to raise to. * * @return This routine returns the old running level. * * @since XT 1.0 */ XTCLINK XTFASTCALL KRUNLEVEL KeRaiseRunLevel(KRUNLEVEL RunLevel) { return KE::RunLevel::RaiseRunLevel(RunLevel); } /** * Reads semaphore's current signal state. * * @param Semaphore * Supplies a pointer to a semaphore object. * * @return This routine returns the current signal state of the semaphore. * * @since XT 1.0 */ XTCLINK XTAPI LONG KeReadSemaphoreState(IN PKSEMAPHORE Semaphore) { return KE::Semaphore::ReadState(Semaphore); } /** * Releases a queued spinlock. * * @param LockLevel * Supplies the queued spinlock level. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTFASTCALL VOID KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_LEVEL LockLevel) { KE::SpinLock::ReleaseQueuedSpinLock(LockLevel); } /** * Releases a semaphore. * * @param Semaphore * Supplies a pointer to a semaphore object. * * @param Increment * Specifies the priority increment value of the semaphore. * * @param Adjustment * Specifies adjustment value added to the semaphore's initial count value. * * @param Wait * Determines whether release of the semaphore will be followed by a kernel wait routine call or not. * * @return This routine returns a previous signal state of the semaphore. * * @since NT 3.5 */ XTCLINK XTAPI LONG KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait) { return KE::Semaphore::ReleaseSemaphore(Semaphore, Increment, Adjustment, Wait); } /** * Releases a kernel spin lock. * * @param SpinLock * Supplies a pointer to the kernel spin lock. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTFASTCALL VOID KeReleaseSpinLock(IN OUT PKSPIN_LOCK SpinLock) { KE::SpinLock::ReleaseSpinLock(SpinLock); } /** * Releases system resource. * * @param ResourceHeader * Specifies a pointer to the system resource header. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID KeReleaseSystemResource(IN PSYSTEM_RESOURCE_HEADER ResourceHeader) { KE::SystemResources::ReleaseResource(ResourceHeader); } /** * Sets the target processor number for DPC. * * @param Dpc * Supplies a pointer to the DPC object. * * @param Number * Supplies the target processor number. * * @return This routine does not return any value. * * @since NT 4.0 */ XTCLINK XTAPI VOID KeSetTargetProcessorDpc(IN PKDPC Dpc, IN CCHAR Number) { KE::Dpc::SetTargetProcessor(Dpc, Number); } /** * Sets the maximum and minimum time increment values in 100ns units. * * @param MaxIncrement * Supplies the maximum time increment. * * @param MinIncrement * Supplies the minimum time increment. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID KeSetTimeIncrement(IN ULONG MaxIncrement, IN ULONG MinIncrement) { KE::SystemTime::SetTimeIncrement(MaxIncrement, MinIncrement); } /** * Sets the supplied timer to expire at the specified time. * * @param Timer * Supplies a pointer to a timer object. * * @param DueTime * Supplies the time at which the timer should expire (both absolute and relative times are supported). * * @param Period * Supplies the timer period. * * @param Dpc * Supplies a pointer to a Deferred Procedure Call (DPC) object. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID KeSetTimer(IN PKTIMER Timer, IN LARGE_INTEGER DueTime, IN LONG Period, IN PKDPC Dpc) { KE::Timer::SetTimer(Timer, DueTime, Period, Dpc); } /** * Decrements the DPC call barier. * * @param SystemArgument * Supplies an address of the DPC call barrier. * * @return This routine does not return any value. * * @since NT 5.2 */ XTCLINK XTAPI VOID KeSignalCallDpcDone(IN PVOID SystemArgument) { KE::Dpc::SignalCallDone(SystemArgument); } /** * Decrements the DPC call reverse barier. * * @param SystemArgument * Supplies an address of the DPC call barrier. * * @return This routine returns TRUE if just one processor is waiting on the barrier, FALSE if more. * * @since NT 5.2 */ XTCLINK XTAPI BOOLEAN KeSignalCallDpcSynchronize(IN PVOID SystemArgument) { return KE::Dpc::SignalCallSynchronize(SystemArgument); } ================================================ FILE: xtoskrnl/ke/i686/dispatch.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/i686/dispatch.cc * DESCRIPTION: Kernel Thread Dispatcher * DEVELOPERS: Rafal Kupiec */ #include /** * Entry point for thread context switching. * * @param CurrentThread * Pointer to the KTHREAD structure of the current thread being suspended. * * @param RunLevel * Supplies the running level at which the wait was initiated. * * @return This routine returns TRUE if a kernel APC is pending and can be delivered, or FALSE otherwise. * * @since XT 1.0 */ XTFASTCALL BOOLEAN KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread, IN KRUNLEVEL RunLevel) { BOOLEAN PendingApc; /* Save registers to the exception frame and invoke the stack switch routine */ __asm__ volatile("subl %[ExFrameSize], %%esp\n" "movl %%esi, %c[ExEsi](%%esp)\n" "movl %%edi, %c[ExEdi](%%esp)\n" "movl %%ebx, %c[ExEbx](%%esp)\n" "movl %%ebp, %c[ExEbp](%%esp)\n" "call %P[SwitchRoutine]\n" "movl %c[ExEbp](%%esp), %%ebp\n" "movl %c[ExEbx](%%esp), %%ebx\n" "movl %c[ExEdi](%%esp), %%edi\n" "movl %c[ExEsi](%%esp), %%esi\n" "addl %[ExFrameSize], %%esp\n" : "=a" (PendingApc) : "c" (CurrentThread), "d" (RunLevel), [ExFrameSize] "i" (sizeof(KEXCEPTION_FRAME) - 4), [ExEbp] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Ebp)), [ExEbx] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Ebx)), [ExEdi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Edi)), [ExEsi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Esi)), [SwitchRoutine] "i" (SwitchThreadStack) : "cc", "memory"); /* Return the APC status */ return PendingApc; } /** * Switches context from current thread to the new thread. * * @param CurrentThread * Pointer to the KTHREAD structure of the current thread being suspended. * * @param ApcBypass * Indicates whether the APC delivery should be bypassed. * * @return This routine returns TRUE if a kernel APC is pending and can be delivered, or FALSE otherwise. * * @since XT 1.0 */ XTFASTCALL BOOLEAN KE::Dispatcher::SwitchThreadContext(IN PKTHREAD CurrentThread, IN BOOLEAN ApcBypass) { UNIMPLEMENTED; return FALSE; } /** * Switches the thread stack and performs necessary operations to prepare for context switching. * * @param CurrentThread * Pointer to the KTHREAD structure of the current thread being suspended. * * @param RunLevel * Supplies the running level at which the wait was initiated. * * @return This routine returns TRUE if a kernel APC is pending and can be delivered, or FALSE otherwise. * * @since XT 1.0 */ XTFASTCALL BOOLEAN KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread, IN KRUNLEVEL RunLevel) { BOOLEAN PendingApc; /* Save old state, synchronize with CPUs, switch stack and call the switch routine */ __asm__ volatile("subl %[FrameSize], %%esp\n" "movl %%fs:%c[PrcbcCurrentThread], %%ebx\n" "BusyLoop:\n" "cmpb $0, %c[ThrdSwapBusy](%%ebx)\n" "je ExitLoop\n" "pause\n" "jmp BusyLoop\n" "ExitLoop:\n" "movl %%fs:%c[ThrdInfoExceptions], %%eax\n" "movl %%eax, %c[SwExceptionList](%%esp)\n" "movb %%dl, %c[SwApcBypass](%%esp)\n" "movl %%esp, %c[ThrdStack](%%ecx)\n" "movl %c[ThrdStack](%%ebx), %%esp\n" "movzbl %c[SwApcBypass](%%esp), %%edx\n" "call %P[SwitchRoutine]\n" "addl %[FrameSize], %%esp\n" : "=a" (PendingApc) : "c" (CurrentThread), "d" (RunLevel), [FrameSize] "i" (sizeof(KSWITCH_FRAME) - 4), [PrcbcCurrentThread] "i" (FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread)), [SwApcBypass] "i" (FIELD_OFFSET(KSWITCH_FRAME, ApcBypassDisabled)), [SwExceptionList] "i" (FIELD_OFFSET(KSWITCH_FRAME, ExceptionList)), [SwitchRoutine] "i" (SwitchThreadContext), [ThrdInfoExceptions] "i" (FIELD_OFFSET(THREAD_INFORMATION_BLOCK, ExceptionList)), [ThrdStack] "i" (FIELD_OFFSET(KTHREAD, KernelStack)), [ThrdSwapBusy] "i" (FIELD_OFFSET(KTHREAD, SwapBusy)) : "cc", "memory"); /* Return the APC status */ return PendingApc; } ================================================ FILE: xtoskrnl/ke/i686/krnlinit.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/i686/krnlinit.cc * DESCRIPTION: CPU architecture specific kernel initialization * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Bootstraps an Application Processor (AP) into the active kernel. This routine is executed exclusively by secondary * processors after being awakened by the BSP. It is called directly from the startup trampoline. * * @param StartBlock * Supplies a pointer to the processor start block containing initialization information provided by the kernel. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KernelInit::BootstrapApplicationProcessor(IN PPROCESSOR_START_BLOCK StartBlock) { PKPROCESSOR_BLOCK ProcessorBlock; /* Initialize application CPU */ AR::ProcessorSupport::InitializeProcessor(StartBlock->ProcessorStructures); /* Initialize processor */ HL::Cpu::InitializeProcessor(); /* Raise to HIGH runlevel */ KE::RunLevel::RaiseRunLevel(HIGH_LEVEL); /* Mark processor as started */ StartBlock->Started = TRUE; /* Get current processor block */ ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); /* Enter infinite loop */ DebugPrint(L"KernelInit::BootstrapApplicationProcessor() finished for CPU #%lu. Entering infinite loop.\n", ProcessorBlock->CpuNumber); KE::Crash::HaltSystem(); } /** * Bootstraps the XT kernel and global subsystems. This routine is executed exclusively by the Bootstrap Processor * and it is called immediately after switching to the kernel boot stack. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KernelInit::BootstrapKernel(VOID) { PKPROCESSOR_CONTROL_BLOCK Prcb; ULONG_PTR PageDirectory[2]; PKPROCESS CurrentProcess; PKTHREAD CurrentThread; /* Get processor control block and current thread */ Prcb = KE::Processor::GetCurrentProcessorControlBlock(); CurrentThread = KE::Processor::GetCurrentThread(); /* Get current process */ CurrentProcess = CurrentThread->ApcState.Process; /* Initialize CPU power state structures */ PO::Idle::InitializeProcessorIdleState(Prcb); /* Save processor state */ KE::Processor::SaveProcessorState(&Prcb->ProcessorState); /* Initialize spin locks */ KE::SpinLock::InitializeAllLocks(); KE::SpinLock::InitializeLockQueues(); /* Lower to APC runlevel */ KE::RunLevel::LowerRunLevel(APC_LEVEL); /* Initialize XTOS kernel */ InitializeKernel(); /* Initialize Idle process */ PageDirectory[0] = 0; PageDirectory[1] = 0; KE::KProcess::InitializeProcess(CurrentProcess, 0, MAXULONG_PTR, PageDirectory, FALSE); CurrentProcess->Quantum = MAXCHAR; /* Initialize Idle thread */ KE::KThread::InitializeThread(CurrentProcess, CurrentThread, NULLPTR, NULLPTR, NULLPTR, NULLPTR, NULLPTR, AR::ProcessorSupport::GetBootStack(), TRUE); CurrentThread->NextProcessor = Prcb->CpuNumber; CurrentThread->Priority = THREAD_HIGH_PRIORITY; CurrentThread->State = Running; CurrentThread->Affinity = (ULONG_PTR)1 << Prcb->CpuNumber; CurrentThread->WaitRunLevel = DISPATCH_LEVEL; CurrentProcess->ActiveProcessors |= (ULONG_PTR)1 << Prcb->CpuNumber; /* Initialize Memory Manager */ MM::Manager::InitializeMemoryManager(); /* Enable shadow buffer for framebuffer */ HL::FrameBuffer::EnableShadowBuffer(); /* Start all application processors */ KE::Processor::InitializeProcessorBlocks(); HL::Cpu::StartAllProcessors(); /* Enter infinite loop */ DebugPrint(L"KernelInit::BootstrapKernel() finished. Entering infinite loop.\n"); KE::Crash::HaltSystem(); } /** * This routine initializes XT kernel. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KernelInit::InitializeKernel(VOID) { XTSTATUS Status; /* Initialize hardware layer subsystem */ Status = HL::Init::InitializeSystem(); if(Status != STATUS_SUCCESS) { /* Hardware layer initialization failed, kernel panic */ DebugPrint(L"Failed to initialize hardware layer subsystem!\n"); KE::Crash::Panic(0); } } /** * Performs architecture-specific initialization for the kernel executive. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KernelInit::InitializeMachine(VOID) { /* Re-enable IDE interrupts */ HL::IoPort::WritePort8(0x376, 0); HL::IoPort::WritePort8(0x3F6, 0); /* Initialize frame buffer */ HL::FrameBuffer::InitializeFrameBuffer(); /* Initialize page map support */ MM::Paging::InitializePageMapSupport(); /* Initialize Kernel Shared Data (KSD) */ KE::SharedData::InitializeKernelSharedData(); /* Initialize processor */ HL::Cpu::InitializeProcessor(); } /** * Switches execution to a new boot stack and transfers control to the KernelInit::StartKernel() routine. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KernelInit::SwitchBootStack(VOID) { ULONG_PTR Stack; PVOID StartKernel; /* Calculate the stack pointer at the top of the buffer, ensuring it is properly aligned as required by the ABI */ Stack = ((ULONG_PTR)AR::ProcessorSupport::GetBootStack() & ~(STACK_ALIGNMENT - 1)); /* Get address of KernelInit::StartKernel() */ StartKernel = (PVOID)KE::KernelInit::BootstrapKernel; /* Discard old stack frame, switch stack, make space for NPX and jump to KernelInit::StartKernel() */ __asm__ volatile("movl %[Stack], %%esp\n" "subl %[TotalSize], %%esp\n" "xorl %%ebp, %%ebp\n" "pushl %[Cr0Value]\n" "jmp *%[TargetRoutine]\n" : : [Cr0Value] "i" (CR0_EM | CR0_MP | CR0_TS), [Stack] "r" (Stack), [TargetRoutine] "r" (StartKernel), [TotalSize] "i" (KTRAP_FRAME_ALIGN + KTRAP_FRAME_SIZE + NPX_FRAME_SIZE + KRETURN_ADDRESS_SIZE) : "ebp", "esp", "memory"); } ================================================ FILE: xtoskrnl/ke/i686/kthread.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/i686/kthread.cc * DESCRIPTION: I686 thread manipulation support * DEVELOPERS: Rafal Kupiec */ #include /** * Initializes CPU architecture dependent context of a thread. * * @param Thread * Supplies a pointer to the thread being initialized. * * @param SystemRoutine * Supplies a pointer to the routine called during first scheduling. * * @param StartRoutine * Supplies a pointer to the routine called during thread startup. * * @param StartContext * Supplies a pointer to a context data that will be passed to start routine. * * @param ContextRecord * Supplies a pointer to a context record which stores the initial state of the user mode thread. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KThread::InitializeThreadContext(IN PKTHREAD Thread, IN PKSYSTEM_ROUTINE SystemRoutine, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext, IN PCONTEXT ContextRecord) { PKTHREAD_INIT_FRAME ThreadFrame; PFX_SAVE_FORMAT FxSaveFormat; /* Set initial thread frame */ ThreadFrame = (PKTHREAD_INIT_FRAME)((ULONG_PTR)Thread->InitialStack - sizeof(KTHREAD_INIT_FRAME)); /* Fill floating point save area with zeroes */ RTL::Memory::ZeroMemory(&ThreadFrame->NpxFrame, sizeof(FX_SAVE_AREA)); /* Check if context provided for this thread */ if(ContextRecord) { /* User mode thread needs further initialization, this is not completed */ UNIMPLEMENTED; /* Fill trap frame with zeroes */ RTL::Memory::ZeroMemory(&ThreadFrame->TrapFrame, sizeof(KTRAP_FRAME)); /* Disable debug registers and enable context registers */ ContextRecord->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS | CONTEXT_CONTROL; /* This is user mode thread */ ThreadFrame->StartFrame.UserMode = TRUE; Thread->PreviousMode = UserMode; /* Disable coprocessor floating point state */ Thread->NpxState = NPX_STATE_UNLOADED; Thread->Header.NpxIrql = PASSIVE_LEVEL; /* Set initial floating point state */ FxSaveFormat = (PFX_SAVE_FORMAT)ContextRecord->ExtendedRegisters; FxSaveFormat->ControlWord = 0x27F; FxSaveFormat->MxCsr = 0x1F80; ContextRecord->FloatSave.Cr0NpxState = 0; ThreadFrame->NpxFrame.Cr0NpxState = 0; ThreadFrame->NpxFrame.NpxSavedCpu = 0; /* Clear DR6 and DR7 registers */ ThreadFrame->TrapFrame.Dr6 = 0; ThreadFrame->TrapFrame.Dr7 = 0; /* Set DS, ES and SS segments for user mode */ ThreadFrame->TrapFrame.SegDs |= RPL_MASK; ThreadFrame->TrapFrame.SegEs |= RPL_MASK; ThreadFrame->TrapFrame.SegSs |= RPL_MASK; /* Set user mode thread in the trap frame */ ThreadFrame->TrapFrame.PreviousMode = UserMode; } else { /* This is kernel mode thread */ ThreadFrame->StartFrame.UserMode = FALSE; Thread->PreviousMode = KernelMode; /* Disable coprocessor floating point state */ Thread->NpxState = NPX_STATE_UNLOADED; /* Set initial floating point state */ ThreadFrame->NpxFrame.FxArea.ControlWord = 0x27F; ThreadFrame->NpxFrame.FxArea.MxCsr = 0x1F80; } /* Initialize thread startup information */ ThreadFrame->StartFrame.StartContext = StartContext; ThreadFrame->StartFrame.StartRoutine = StartRoutine; ThreadFrame->StartFrame.SystemRoutine = SystemRoutine; /* Initialize switch frame */ ThreadFrame->SwitchFrame.ApcBypassDisabled = TRUE; ThreadFrame->SwitchFrame.ExceptionList = (PEXCEPTION_REGISTRATION_RECORD) - 1; /* Set thread stack */ Thread->KernelStack = &ThreadFrame->SwitchFrame; } ================================================ FILE: xtoskrnl/ke/i686/proc.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/i686/proc.c * DESCRIPTION: I686 processor-related functionality for the kernel * DEVELOPERS: Rafal Kupiec */ #include /** * Gets the processor block for the currently executing processor. * * @return This routine returns the current processor block read from the FS register. * * @since XT 1.0 */ XTAPI PKPROCESSOR_BLOCK KE::Processor::GetCurrentProcessorBlock(VOID) { /* Get processor block from FS register */ return (PKPROCESSOR_BLOCK)AR::CpuFunctions::ReadFSDualWord(FIELD_OFFSET(KPROCESSOR_BLOCK, Self)); } /** * Gets the processor control block for the currently executing processor. * * @return This routine returns the current processor control block read from the FS register. * * @since XT 1.0 */ XTAPI PKPROCESSOR_CONTROL_BLOCK KE::Processor::GetCurrentProcessorControlBlock(VOID) { return (PKPROCESSOR_CONTROL_BLOCK)AR::CpuFunctions::ReadFSDualWord(FIELD_OFFSET(KPROCESSOR_BLOCK, CurrentPrcb)); } /** * Gets the number of the currently executing processor. * * @return This routine returns the zero-indexed processor number. * * @since XT 1.0 */ XTAPI ULONG KE::Processor::GetCurrentProcessorNumber(VOID) { return (ULONG)AR::CpuFunctions::ReadFSDualWord(FIELD_OFFSET(KPROCESSOR_BLOCK, CpuNumber)); } /** * Gets the current thread running on the currently executing processor. * * @return This routine returns the address of the current thread object. * * @since NT 3.5 */ XTAPI PKTHREAD KE::Processor::GetCurrentThread(VOID) { return (PKTHREAD)AR::CpuFunctions::ReadFSDualWord(FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread)); } /** * Gets the processor block for the specified processor number. * * @param CpuNumber * Supplies the zero-indexed processor number. * * @return This routine returns a pointer to the processor block, or NULLPTR if invalid. * * @since XT 1.0 */ XTAPI PKPROCESSOR_BLOCK KE::Processor::GetProcessorBlock(IN ULONG CpuNumber) { /* Check if the requested CPU number is within dynamic bounds */ if(CpuNumber >= InstalledCpus || ProcessorBlocks == NULLPTR || ProcessorBlocks[CpuNumber] == NULLPTR) { /* Invalid CPU number, return NULLPTR */ return NULLPTR; } /* Return requested processor block */ return ProcessorBlocks[CpuNumber]; } /** * Initializes the global processor structures by allocating an array of processor block pointers. * * @return This routine returns a status code indicating the success or failure of the allocation. * * @since XT 1.0 */ XTAPI XTSTATUS KE::Processor::InitializeProcessorBlocks() { PACPI_SYSTEM_INFO SystemInfo; XTSTATUS Status; /* Save number of CPUs installed */ HL::Acpi::GetSystemInformation(&SystemInfo); InstalledCpus = SystemInfo->CpuCount; /* Allocate an array of pointers */ Status = MM::Allocator::AllocatePool(NonPagedPool, InstalledCpus * sizeof(PKPROCESSOR_BLOCK), (PVOID*)&ProcessorBlocks); if(Status != STATUS_SUCCESS) { /* Failed to allocate memory, return error */ return Status; } /* Zero the array initially */ RTL::Memory::ZeroMemory(ProcessorBlocks, InstalledCpus * sizeof(PKPROCESSOR_BLOCK)); /* Return success */ return STATUS_SUCCESS; } /** * Registers the hardware APIC ID for the currently executing processor. * * @param ApicId * Supplies the hardware APIC ID to register in the processor block. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::Processor::RegisterHardwareId(IN ULONG HardwareId) { PKPROCESSOR_BLOCK CurrentBlock; /* Retrieve the processor block for the executing core */ CurrentBlock = GetCurrentProcessorBlock(); if(CurrentBlock != NULLPTR) { /* Register the hardware identifier for IPI targeting */ CurrentBlock->HardwareId = HardwareId; } } /** * Registers or deregisters a processor block in the global CPU table. * * @param CpuNumber * Specifies the logical processor number. * * @param ProcessorBlock * Supplies a pointer to the processor block. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::Processor::RegisterProcessorBlock(ULONG CpuNumber, PKPROCESSOR_BLOCK ProcessorBlock) { /* Check if the requested CPU number is within dynamic bounds */ if(ProcessorBlocks != NULLPTR && CpuNumber < InstalledCpus) { /* Register processor block */ ProcessorBlocks[CpuNumber] = ProcessorBlock; } } /** * Saves the current processor state. * * @param State * Supplies a pointer to the processor state structure. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::Processor::SaveProcessorState(OUT PKPROCESSOR_STATE CpuState) { /* Save CR registers */ CpuState->SpecialRegisters.Cr0 = AR::CpuFunctions::ReadControlRegister(0); CpuState->SpecialRegisters.Cr2 = AR::CpuFunctions::ReadControlRegister(2); CpuState->SpecialRegisters.Cr3 = AR::CpuFunctions::ReadControlRegister(3); CpuState->SpecialRegisters.Cr4 = AR::CpuFunctions::ReadControlRegister(4); /* Save DR registers */ CpuState->SpecialRegisters.KernelDr0 = AR::CpuFunctions::ReadDebugRegister(0); CpuState->SpecialRegisters.KernelDr1 = AR::CpuFunctions::ReadDebugRegister(1); CpuState->SpecialRegisters.KernelDr2 = AR::CpuFunctions::ReadDebugRegister(2); CpuState->SpecialRegisters.KernelDr3 = AR::CpuFunctions::ReadDebugRegister(3); CpuState->SpecialRegisters.KernelDr6 = AR::CpuFunctions::ReadDebugRegister(6); CpuState->SpecialRegisters.KernelDr7 = AR::CpuFunctions::ReadDebugRegister(7); /* Save GDT, IDT, LDT and TaskRegister */ AR::CpuFunctions::StoreGlobalDescriptorTable(&CpuState->SpecialRegisters.Gdtr.Limit); AR::CpuFunctions::StoreInterruptDescriptorTable(&CpuState->SpecialRegisters.Idtr.Limit); AR::CpuFunctions::StoreLocalDescriptorTable(&CpuState->SpecialRegisters.Ldtr); AR::CpuFunctions::StoreTaskRegister(&CpuState->SpecialRegisters.Tr); } ================================================ FILE: xtoskrnl/ke/kprocess.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/kprocess.cc * DESCRIPTION: XT kernel process manipulation support * DEVELOPERS: Rafal Kupiec */ #include XTAPI PEPROCESS KE::KProcess::GetInitialProcess(VOID) { return &InitialProcess; } /** * Initializes the process. * * @param Process * Supplies a pointer to process that will be initialized. * * @param Priority * Specifies the process priority. * * @param Affinity * Specifies a process affinity designating processors on which process can run. * * @param DirectoryTable * Supplies a pointer to the directory table. * * @param Alignment * Specifies the exceptions alignment of the process. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID KE::KProcess::InitializeProcess(IN OUT PKPROCESS Process, IN KPRIORITY Priority, IN KAFFINITY Affinity, IN PULONG_PTR DirectoryTable, IN BOOLEAN Alignment) { /* Initialize process dispatcher header */ Process->Header.Type = ProcessObject; /* Initialize process wait list */ RtlInitializeListHead(&Process->Header.WaitListHead); /* Initialize process list heads */ RtlInitializeListHead(&Process->ProfileListHead); RtlInitializeListHead(&Process->ReadyListHead); RtlInitializeListHead(&Process->ThreadListHead); /* Set base process properties */ Process->BasePriority = Priority; Process->Affinity = Affinity; Process->AutoAlignment = Alignment; Process->DirectoryTable[0] = DirectoryTable[0]; Process->DirectoryTable[1] = DirectoryTable[1]; Process->StackCount = MAXSHORT; /* Set thread quantum */ Process->Quantum = THREAD_QUANTUM; /* Set IOPM offset */ Process->IopmOffset = sizeof(KTSS); /* Set initial process state */ Process->State = ProcessInMemory; } ================================================ FILE: xtoskrnl/ke/krnlinit.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/krnlinit.cc * DESCRIPTION: XT kernel initialization * DEVELOPERS: Rafal Kupiec */ #include /* Use routines from Kernel Library */ using namespace KE; /** * This routine starts up the XT kernel. It is called by boot loader. * * @param Parameters * Supplies a pointer to memory area containing parameters passed to kernel by bootloader. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KeStartXtSystem(IN PKERNEL_INITIALIZATION_BLOCK Parameters) { /* Verify kernel and boot loader compatibility */ if(Parameters->BlockSize != sizeof(KERNEL_INITIALIZATION_BLOCK) || Parameters->BlockVersion != INITIALIZATION_BLOCK_VERSION || Parameters->ProtocolVersion != BOOT_PROTOCOL_VERSION) { /* Kernel and boot loader version mismatch */ KE::Crash::HaltSystem(); } /* Save the kernel initialization block */ KE::BootInformation::InitializeInitializationBlock(Parameters); /* Check if debugging enabled and if boot loader provided routine for debug printing */ if(DEBUG && KE::BootInformation::GetDebugPrint()) { /* Use loader's provided DbgPrint() routine for early printing to serial console */ KD::DebugIo::SetPrintRoutine(KE::BootInformation::GetDebugPrint()); DebugPrint(L"Initializing ExectOS v%d.%d for %s\n", XTOS_VERSION_MAJOR, XTOS_VERSION_MINOR, _ARCH_NAME); } /* Initialize boot CPU and set the unhandled interrupt routine */ AR::ProcessorSupport::InitializeProcessor(NULLPTR); AR::Traps::SetUnhandledInterruptRoutine(HL::Irq::HandleUnexpectedInterrupt); /* Initialize system resources */ KE::SystemResources::InitializeResources(); /* Check if debugging enabled */ if(DEBUG) { /* Initialize debug I/O */ KD::DebugIo::InitializeDebugIoProviders(); } /* Announce kernel startup */ DebugPrint(L"Starting ExectOS v%d.%d for %s (%s-%s-%s-%s / %s %s)\n", XTOS_VERSION_MAJOR, XTOS_VERSION_MINOR, _ARCH_NAME, XTOS_VERSION_DATE, XTOS_VERSION_BUILD, XTOS_VERSION_ARCH, XTOS_VERSION_HASH, XTOS_COMPILER_NAME, XTOS_COMPILER_VERSION); /* Architecture specific kernel initialization */ KE::KernelInit::InitializeMachine(); /* Raise to HIGH runlevel */ KE::RunLevel::RaiseRunLevel(HIGH_LEVEL); /* Switch the boot stack and transfer control to the KepStartKernel() routine */ KE::KernelInit::SwitchBootStack(); } ================================================ FILE: xtoskrnl/ke/kthread.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/kthread.cc * DESCRIPTION: XT kernel thread manipulation support * DEVELOPERS: Rafal Kupiec */ #include XTAPI PETHREAD KE::KThread::GetInitialThread(VOID) { return &InitialThread; } /** * Initializes the thread. * * @param Process * Supplies a pointer to the process that owns the thread. * * @param Thread * Supplies a pointer to thread that will be initialized. * * @param SystemRoutine * Supplies a pointer to the routine called during first scheduling. * * @param StartRoutine * Supplies a pointer to the routine called during thread startup. * * @param StartContext * Supplies a pointer to a context data that will be passed to start routine. * * @param Context * Supplies a pointer to the context frame containing state of the user mode thread. * * @param EnvironmentBlock * Supplies a pointer to the environment block of the thread. * * @param Stack * Supplies a pointer to the stack of the thread. * * @return This routine returns a status code. * * @since NT 3.5 */ XTAPI XTSTATUS KE::KThread::InitializeThread(IN PKPROCESS Process, IN OUT PKTHREAD Thread, IN PKSYSTEM_ROUTINE SystemRoutine, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext, IN PCONTEXT Context, IN PVOID EnvironmentBlock, IN PVOID Stack, IN BOOLEAN RunThread) { PKWAIT_BLOCK TimerWaitBlock; BOOLEAN Allocation; XTSTATUS Status; ULONG Index; /* No stack allocation was done yet */ Allocation = FALSE; /* Initialize thread dispatcher header */ Thread->Header.Type = ThreadObject; Thread->Header.SignalState = 0; /* Initialize thread wait list */ RTL::LinkedList::InitializeListHead(&Thread->Header.WaitListHead); /* Initialize thread mutant list head */ RTL::LinkedList::InitializeListHead(&Thread->MutantListHead); /* Initialize the builtin wait blocks */ for(Index = 0; Index <= KTHREAD_WAIT_BLOCK; Index++) { Thread->WaitBlock[Index].Thread = Thread; } /* Initialize stack resident and stack swap */ Thread->AutoAlignment = Process->AutoAlignment; Thread->StackResident = TRUE; Thread->StackSwap = TRUE; Thread->SwapBusy = FALSE; /* Set priority adjustment reason */ Thread->AdjustReason = AdjustNone; /* Initialize thread lock */ KE::SpinLock::InitializeSpinLock(&Thread->ThreadLock); /* Initialize thread APC */ Thread->ApcStatePointer[0] = &Thread->ApcState; Thread->ApcStatePointer[1] = &Thread->SavedApcState; Thread->ApcQueueable = TRUE; Thread->ApcState.Process = Process; Thread->Process = Process; /* Initialize APC list heads */ RTL::LinkedList::InitializeListHead(&Thread->ApcState.ApcListHead[KernelMode]); RTL::LinkedList::InitializeListHead(&Thread->ApcState.ApcListHead[UserMode]); /* Initialize APC queue lock */ KE::SpinLock::InitializeSpinLock(&Thread->ApcQueueLock); /* Initialize kernel-mode suspend APC */ KE::Apc::InitializeApc(&Thread->SuspendApc, Thread, OriginalApcEnvironment, SuspendNop, SuspendRundown, SuspendThread, KernelMode, NULLPTR); /* Initialize suspend semaphore */ KE::Semaphore::InitializeSemaphore(&Thread->SuspendSemaphore, 0, 2); /* Initialize the builtin timer */ KE::Timer::InitializeTimer(&Thread->Timer, NotificationTimer); TimerWaitBlock = &Thread->WaitBlock[KTIMER_WAIT_BLOCK]; TimerWaitBlock->Object = &Thread->Timer; TimerWaitBlock->WaitKey = STATUS_TIMEOUT; TimerWaitBlock->WaitType = WaitAny; TimerWaitBlock->WaitListEntry.Flink = &(&Thread->Timer)->Header.WaitListHead; TimerWaitBlock->WaitListEntry.Blink = &(&Thread->Timer)->Header.WaitListHead; /* Initialize Thread Environment Block*/ Thread->EnvironmentBlock = (PTHREAD_ENVIRONMENT_BLOCK)EnvironmentBlock; /* Make sure there is a valid stack available */ if(!Stack) { /* Allocate new stack */ Status = MM::KernelPool::AllocateKernelStack(&Stack, KERNEL_STACK_SIZE); if(Status != STATUS_SUCCESS || !Stack) { /* Stack allocation failed */ return STATUS_INSUFFICIENT_RESOURCES; } /* Mark allocation as successful */ Allocation = TRUE; } Thread->InitialStack = Stack; Thread->StackBase = Stack; Thread->StackLimit = (PVOID)((ULONG_PTR)Stack - KERNEL_STACK_SIZE); __try { /* Initialize thread context */ InitializeThreadContext(Thread, SystemRoutine, StartRoutine, StartContext, Context); } __except(EXCEPTION_EXECUTE_HANDLER) { /* Failed to initialize thread context, check stack allocation */ if(Allocation) { /* Deallocate stack */ MM::KernelPool::FreeKernelStack(Stack, FALSE); Thread->InitialStack = NULLPTR; Thread->StackBase = NULLPTR; } /* Thread initialization failed */ return STATUS_UNSUCCESSFUL; } /* Mark thread as initialized and run it */ Thread->State = Initialized; /* Check if thread should be started */ if(RunThread) { /* Start thread */ StartThread(Thread); } /* Return success */ return STATUS_SUCCESS; } /** * Starts the thread. * * @param Thread * Supplies a pointer to the thread. * * @return This routine does not return any value. * * @since NT 5.1 */ XTAPI VOID KE::KThread::StartThread(IN PKTHREAD Thread) { UNIMPLEMENTED; } /** * Suspend APC-built thread NOP routine. It takes no actions. * * @param Apc * Supplies a pointer to the APC object. * * @param NormalRoutine * Supplies a pointer to the normal routine set during the APC initialization. Unused by this routine. * * @param NormalContext * Supplies a pointer a context data set during the APC initialization. Unused by this routine. * * @param SystemArgument1 * Supplies a pointer to an unused system argument. * * @param SystemArgument2 * Supplies a pointer to an unused system argument. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KThread::SuspendNop(IN PKAPC Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2) { /* No action here */ } /** * Suspend APC-built thread rundown routine. It takes no actions. * * @param Apc * Supplies a pointer to the APC object. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KThread::SuspendRundown(IN PKAPC Apc) { /* No action here */ } /** * Suspends thread execution by waiting on the thread's semaphore. * * @param NormalContext * Supplies a pointer a context data set during the APC initialization. Unused by this routine. * * @param SystemArgument1 * Supplies a pointer to an unused system argument. * * @param SystemArgument2 * Supplies a pointer to an unused system argument. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::KThread::SuspendThread(IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2) { UNIMPLEMENTED; } ================================================ FILE: xtoskrnl/ke/kubsan.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/kubsan.cc * DESCRIPTION: Kernel Undefined Behaviour Sanitizer (UBSAN) error reporting handler * DEVELOPERS: Rafal Kupiec */ #include /** * Checks whether handled UBSAN error should be reported. * * @param Location * Supplies a pointer to the UBSAN location descriptor. * * @return This routine returns TRUE if UBSAN error should be reported, or FALSE otherwise. * * @since XT 1.0 */ XTCDECL BOOLEAN KE::KUbsan::CheckReport(PKUBSAN_SOURCE_LOCATION Location) { /* Make sure, this error should be reported */ return !ActiveFrame; } /** * Enters UBSAN frame and marks it as active. * * @param Location * Supplies a pointer to the UBSAN location descriptor. * * @param Reason * Supplies a pointer to the reason of the UBSAN failure. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::EnterFrame(PKUBSAN_SOURCE_LOCATION Location, PCCHAR Reason) { /* Enter UBSAN frame */ ActiveFrame = TRUE; /* Print generic error message to debug console */ DebugPrint(L"UBSAN: Undefined behavior (%s) in %s:%d:%d\n", Reason, Location->FileName, Location->Line, Location->Column); } /** * Gets signed value from UBSAN. * * @param Type * Supplies a pointer to the UBSAN type descriptor. * * @param Value * Supplies a pointer to the UBSAN value. * * @return This routine returns a 64-bit signed integer. * * @since XT 1.0 */ XTCDECL LONGLONG KE::KUbsan::GetSignedValue(PKUBSAN_TYPE_DESCRIPTOR Type, PVOID Value) { ULONG BitWidth, ExtraBits; ULONG_PTR LongValue; /* Calculate bit width of the type */ BitWidth = 1 << (Type->TypeInfo >> 1); /* Check if inline integer */ if(BitWidth <= sizeof(ULONG) * 8) { /* Calculate extra bits and return value */ ExtraBits = sizeof(LONGLONG) * 8 - BitWidth; LongValue = (ULONG_PTR)Value; return ((LONGLONG)LongValue) << ExtraBits >> ExtraBits; } /* Return 64-bit integer */ return *(PLONGLONG)Value; } /** * Gets a string representation of the UBSAN type kind. * * @param TypeCheckKind * Supplies a UBSAN type kind as a numeric value. * * @return This routine returns a string representation of the UBSAN type. * * @since XT 1.0 */ XTCDECL PCCHAR KE::KUbsan::GetTypeKind(UCHAR TypeCheckKind) { /* Get type kind name */ switch(TypeCheckKind) { case 0: return "Load of"; case 1: return "Store to"; case 2: return "Reference binding to"; case 3: return "Member access within"; case 4: return "Member call on"; case 5: return "Constructor call on"; case 6: return "Downcast of"; case 7: return "Downcast of"; case 8: return "Upcast of"; case 9: return "Cast to virtual base of"; default: return "Unrecognized failure code"; } } /** * Gets unsigned value from UBSAN. * * @param Type * Supplies a pointer to the UBSAN type descriptor. * * @param Value * Supplies a pointer to the UBSAN value. * * @return This routine returns a 64-bit unsigned integer. * * @since XT 1.0 */ XTCDECL ULONGLONG KE::KUbsan::GetUnsignedValue(PKUBSAN_TYPE_DESCRIPTOR Type, PVOID Value) { ULONG BitWidth; /* Calculate bit width of the type */ BitWidth = 1 << (Type->TypeInfo >> 1); /* Check if inline integer */ if(BitWidth <= sizeof(ULONG) * 8) { /* Return value */ return (ULONG_PTR)Value; } /* Return 64-bit integer */ return *(PULONGLONG)Value; } /** * Handles the division overflow error reported by UBSAN. * * @param Data * Supplies a pointer to the UBSAN overflow data. * * @param Lhs * Supplies LHS operand. * * @param Rhs * Supplies RHS operand. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::HandleDivisionOverflow(PKUBSAN_OVERFLOW_DATA Data, PVOID Lhs, PVOID Rhs) { /* Check if this error was already reported */ if(!CheckReport(&Data->Location)) { /* Don't report twice */ return; } /* Enter UBSAN frame */ EnterFrame(&Data->Location, "Division-Overflow"); /* Check if signed type, which value is -1 */ if((Data->Type->TypeInfo & 1) && (GetSignedValue(Data->Type, Rhs) == -1)) { /* Division by -1, print error message to debug console */ DebugPrint(L"UBSAN: Division by -1 cannot be represented in type %s\n", Data->Type->TypeName); } else { /* Division by 0, print error message to debug console */ DebugPrint(L"UBSAN: Division by zero\n"); } /* Leave UBSAN frame */ LeaveFrame(); } /** * Handles the float cast overflow error reported by UBSAN. * * @param Data * Supplies a pointer to the UBSAN float cast overflow data. * * @param Lhs * Supplies LHS operand. * * @param Rhs * Supplies RHS operand. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::HandleFloatCastOverflow(PKUBSAN_FLOAT_CAST_OVERFLOW_DATA Data, ULONG_PTR Lhs, ULONG_PTR Rhs) { /* Check if this error was already reported */ if(!CheckReport(&Data->Location)) { /* Don't report twice */ return; } /* Enter UBSAN frame */ EnterFrame(&Data->Location, "Float-Cast-Overflow"); /* Print error message to debug console */ DebugPrint(L"Value of type %s is outside the range of type %s\n", Data->LhsType->TypeName, Data->RhsType->TypeName); /* Leave UBSAN frame */ LeaveFrame(); } /** * Handles the function type mismatch error reported by UBSAN. * * @param Data * Supplies a pointer to the UBSAN function type mismatch data. * * @param Pointer * Supplies pointer operand. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::HandleFunctionTypeMismatch(PKUBSAN_FUNCTION_TYPE_MISMATCH_DATA Data, ULONG_PTR Pointer) { /* Check if this error was already reported */ if(!CheckReport(&Data->Location)) { /* Don't report twice */ return; } /* Enter UBSAN frame */ EnterFrame(&Data->Location, "Float-Cast-Overflow"); /* Print error message to debug console */ DebugPrint(L"UBSAN: Indirect function call through %P address of a wrong type %s\n", (PVOID)Pointer, Data->Type->TypeName); /* Leave UBSAN frame */ LeaveFrame(); } /** * Handles the integer overflow error reported by UBSAN. * * @param Data * Supplies a pointer to the UBSAN overflow data. * * @param Lhs * Supplies LHS operand. * * @param Rhs * Supplies RHS operand. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::HandleIntegerOverflow(PKUBSAN_OVERFLOW_DATA Data, ULONG_PTR Lhs, ULONG_PTR Rhs) { /* Check if this error was already reported */ if(!CheckReport(&Data->Location)) { /* Don't report twice */ return; } /* Enter UBSAN frame */ EnterFrame(&Data->Location, "Integer-Overflow"); /* Print error message to debug console */ DebugPrint(L"UBSAN: The result of an arithmetic operation cannot be represented in type %s\n", Data->Type->TypeName); /* Leave UBSAN frame */ LeaveFrame(); } /** * Handles the invalid builtin error reported by UBSAN. * * @param Data * Supplies a pointer to the UBSAN invalid builtin data. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::HandleInvalidBuiltin(PKUBSAN_INVALID_BUILTIN_DATA Data) { /* Check if this error was already reported */ if(!CheckReport(&Data->Location)) { /* Don't report twice */ return; } /* Enter UBSAN frame */ EnterFrame(&Data->Location, "Invalid-Builtin"); /* Check kind of UBSAN error */ if(Data->Kind == 0 || Data->Kind == 1) { /* Invalid ctz()/clz() parameter, print error message to debug console */ DebugPrint(L"UBSAN: Passing zero to ctz() or clz() which is not a valid argument\n"); } else { /* Unknown kind, print error message to debug console */ DebugPrint(L"UBSAN: Unknown kind %u\n", Data->Kind); } /* Leave UBSAN frame */ LeaveFrame(); } /** * Handles the misaligned access error reported by UBSAN. * * @param Data * Supplies a pointer to the UBSAN type mismatch data. * * @param Pointer * Supplies a pointer operand. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::HandleMisalignedAccess(PKUBSAN_TYPE_MISMATCH_DATA Data, ULONG_PTR Pointer) { /* Check if this error was already reported */ if(!CheckReport(&Data->Location)) { /* Don't report twice */ return; } /* Enter UBSAN frame */ EnterFrame(&Data->Location, "Misaligned-Access"); /* Print error message to debug console */ DebugPrint(L"UBSAN: %s misaligned address %p for type %s which requires %ld byte alignment\n", GetTypeKind(Data->TypeCheckKind), (PVOID)Pointer, Data->Type->TypeName, Data->Alignment); /* Leave UBSAN frame */ LeaveFrame(); } /** * Handles the negate overflow error reported by UBSAN. * * @param Data * Supplies a pointer to the UBSAN overflow data. * * @param OldValue * Supplies old value. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::HandleNegateOverflow(PKUBSAN_OVERFLOW_DATA Data, ULONG_PTR OldValue) { /* Check if this error was already reported */ if(!CheckReport(&Data->Location)) { /* Don't report twice */ return; } /* Enter UBSAN frame */ EnterFrame(&Data->Location, "Negate-Overflow"); /* Print error message to debug console */ DebugPrint(L"UBSAN: Negation of %lu cannot be represented in type %s\n", OldValue, Data->Type->TypeName); /* Leave UBSAN frame */ LeaveFrame(); } /** * Handles the NULL pointer dereference error reported by UBSAN. * * @param Data * Supplies a pointer to the UBSAN type mismatch data. * * @param Pointer * Supplies a pointer operand. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::HandleNullPointerDereference(PKUBSAN_TYPE_MISMATCH_DATA Data) { /* Check if this error was already reported */ if(!CheckReport(&Data->Location)) { /* Don't report twice */ return; } /* Enter UBSAN frame */ EnterFrame(&Data->Location, "NULL-Pointer-Dereference"); /* Print error message to debug console */ DebugPrint(L"UBSAN: %s NULL pointer of type %s\n", GetTypeKind(Data->TypeCheckKind), Data->Type->TypeName); /* Leave UBSAN frame */ LeaveFrame(); } /** * Handles the object size mismatch error reported by UBSAN. * * @param Data * Supplies a pointer to the UBSAN type mismatch data. * * @param Pointer * Supplies a pointer operand. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::HandleObjectSizeMismatch(PKUBSAN_TYPE_MISMATCH_DATA Data, ULONG_PTR Pointer) { /* Check if this error was already reported */ if(!CheckReport(&Data->Location)) { /* Don't report twice */ return; } /* Enter UBSAN frame */ EnterFrame(&Data->Location, "Object-Size-Mismatch"); /* Print error message to debug console */ DebugPrint(L"UBSAN: %s address %p with insufficient space for an object of type %s\n", GetTypeKind(Data->TypeCheckKind), (PVOID)Pointer, Data->Type->TypeName); /* Leave UBSAN frame */ LeaveFrame(); } /** * Handles the out of bounds error reported by UBSAN. * * @param Data * Supplies a pointer to the UBSAN out of bounds data. * * @param Index * Supplies an index operand. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::HandleOutOfBounds(PKUBSAN_OUT_OF_BOUNDS_DATA Data, ULONG_PTR Index) { /* Check if this error was already reported */ if(!CheckReport(&Data->Location)) { /* Don't report twice */ return; } /* Enter UBSAN frame */ EnterFrame(&Data->Location, "Array-Index-Out-Of-Bounds"); /* Print error message to debug console */ DebugPrint(L"UBSAN: index is out of range for type %s", Data->ArrayType->TypeName); /* Leave UBSAN frame */ LeaveFrame(); } /** * Handles the pointer overflow error reported by UBSAN. * * @param Data * Supplies a pointer to the UBSAN overflow data. * * @param Lhs * Supplies LHS operand. * * @param Rhs * Supplies RHS operand. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::HandlePointerOverflow(PKUBSAN_OVERFLOW_DATA Data, ULONG_PTR Lhs, ULONG_PTR Rhs) { /* Check if this error was already reported */ if(!CheckReport(&Data->Location)) { /* Don't report twice */ return; } /* Enter UBSAN frame */ EnterFrame(&Data->Location, "Pointer-Overflow"); /* Print error message to debug console */ DebugPrint(L"UBSAN: Pointer operation %s %p to %p\n", Lhs > Rhs ? "overflowed" : "underflowed", (PVOID)Lhs, (PVOID)Rhs); /* Leave UBSAN frame */ LeaveFrame(); } /** * Handles the shift out of bounds error reported by UBSAN. * * @param Data * Supplies a pointer to the UBSAN shift out of bounds data. * * @param Lhs * Supplies LHS operand. * * @param Rhs * Supplies RHS operand. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::HandleShiftOutOfBounds(PKUBSAN_SHIFT_OUT_OF_BOUNDS_DATA Data, ULONG_PTR Lhs, ULONG_PTR Rhs) { ULONG LhsBitWidth; /* Check if this error was already reported */ if(!CheckReport(&Data->Location)) { /* Don't report twice */ return; } /* Enter UBSAN frame */ EnterFrame(&Data->Location, "Shift-Out-Of-Bounds"); /* Calculate Lhs bit width */ LhsBitWidth = 1 << (Data->LhsType->TypeInfo >> 1); /* Check a type of out of bounds error */ if((Data->RhsType->TypeInfo & 1) && (GetSignedValue(Data->RhsType, (PVOID)Rhs) < 0)) { /* Negative shift exponent, print error message to debug console */ DebugPrint(L"UBSAN: Shift exponent %lld is negative\n", GetSignedValue(Data->RhsType, (PVOID)Rhs)); } else if((Data->LhsType->TypeInfo & 1) && (GetSignedValue(Data->LhsType, (PVOID)Lhs) < 0)) { /* Negative left shift value, print error message to debug console */ DebugPrint(L"UBSAN: Left shift of negative value %lld\n", GetSignedValue(Data->LhsType, (PVOID)Lhs)); } else if(GetUnsignedValue(Data->RhsType, (PVOID)Rhs) >= LhsBitWidth) { /* Shift exponent too large, print error message to debug console */ DebugPrint(L"UBSAN: Shift exponent %lld is too large for %u-bit type %s\n", GetUnsignedValue(Data->RhsType, (PVOID)Rhs), LhsBitWidth, Data->LhsType->TypeName); } else { /* Left shift too large, print error message to debug console */ DebugPrint(L"UBSAN: Left shift of %lld by %lld places cannot be represented in type %s\n", GetSignedValue(Data->LhsType, (PVOID)Lhs), GetSignedValue(Data->RhsType, (PVOID)Rhs), Data->LhsType->TypeName); } /* Leave UBSAN frame */ LeaveFrame(); } /** * Handles the type mismatch error reported by UBSAN. * * @param Data * Supplies a pointer to the UBSAN type mismatch data. * * @param Pointer * Supplies a pointer operand. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::HandleTypeMismatch(PKUBSAN_TYPE_MISMATCH_DATA Data, ULONG_PTR Pointer) { /* Check the type of mismatch */ if(!Pointer) { /* Handle NULL pointer dereference */ HandleNullPointerDereference(Data); } else if(Data->Alignment && (((Pointer) & ((decltype(Pointer))(Data->Alignment) - 1)) != 0)) { /* Handle misaligned access */ HandleMisalignedAccess(Data, Pointer); } else { /* Handle object size mismatch */ HandleObjectSizeMismatch(Data, Pointer); } } /** * Leaves the UBSAN frame by marking it as inactive. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID KE::KUbsan::LeaveFrame() { /* Leave UBSAN frame */ ActiveFrame = FALSE; } /** * Handles the addition overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. * * @param Data * Supplies a pointer to the UBSAN overflow data. * * @param Lhs * Supplies LHS operand. * * @param Rhs * Supplies RHS operand. * * @return This routine does not return any value. * * @since XT 1.0 * * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 */ XTCLINK XTCDECL VOID __ubsan_handle_add_overflow(IN PKUBSAN_OVERFLOW_DATA Data, IN ULONG_PTR Lhs, IN ULONG_PTR Rhs) { /* Call UBSAN arithmetic overflow handler */ KE::KUbsan::HandleIntegerOverflow(Data, Lhs, Rhs); } /** * Handles the division overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. * * @param Data * Supplies a pointer to the UBSAN overflow data. * * @param Lhs * Supplies LHS operand. * * @param Rhs * Supplies RHS operand. * * @return This routine does not return any value. * * @since XT 1.0 * * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 */ XTCLINK XTCDECL VOID __ubsan_handle_divrem_overflow(IN PKUBSAN_OVERFLOW_DATA Data, IN PVOID Lhs, IN PVOID Rhs) { /* Call UBSAN division overflow handler */ KE::KUbsan::HandleDivisionOverflow(Data, Lhs, Rhs); } /** * Handles the float cast overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. * * @param Data * Supplies a pointer to the UBSAN float cast overflow data. * * @param Lhs * Supplies LHS operand. * * @param Rhs * Supplies RHS operand. * * @return This routine does not return any value. * * @since XT 1.0 * * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 */ XTCLINK XTCDECL VOID __ubsan_handle_float_cast_overflow(IN PKUBSAN_FLOAT_CAST_OVERFLOW_DATA Data, IN ULONG_PTR Lhs, IN ULONG_PTR Rhs) { /* Call UBSAN float cast overflow handler */ KE::KUbsan::HandleFloatCastOverflow(Data, Lhs, Rhs); } /** * Handles the function type mismatch error. This is internal routine implementing ABI defined by CLANG UBSAN. * * @param Data * Supplies a pointer to the UBSAN function type mismatch data. * * @param Pointer * Supplies pointer operand. * * @return This routine does not return any value. * * @since XT 1.0 * * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 */ XTCLINK XTCDECL VOID __ubsan_handle_function_type_mismatch(IN PKUBSAN_FUNCTION_TYPE_MISMATCH_DATA Data, IN ULONG_PTR Pointer) { /* Call UBSAN function type mismatch handler */ KE::KUbsan::HandleFunctionTypeMismatch(Data, Pointer); } /** * Handles the invalid builtin error. This is internal routine implementing ABI defined by CLANG UBSAN. * * @param Data * Supplies a pointer to the UBSAN invalid builtin data. * * @return This routine does not return any value. * * @since XT 1.0 * * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 */ XTCLINK XTCDECL VOID __ubsan_handle_invalid_builtin(IN PKUBSAN_INVALID_BUILTIN_DATA Data) { /* Call UBSAN invalid builtin handler */ KE::KUbsan::HandleInvalidBuiltin(Data); } /** * Handles the multiplication overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. * * @param Data * Supplies a pointer to the UBSAN overflow data. * * @param Lhs * Supplies LHS operand. * * @param Rhs * Supplies RHS operand. * * @return This routine does not return any value. * * @since XT 1.0 * * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 */ XTCLINK XTCDECL VOID __ubsan_handle_mul_overflow(IN PKUBSAN_OVERFLOW_DATA Data, IN ULONG_PTR Lhs, IN ULONG_PTR Rhs) { /* Call UBSAN arithmetic overflow handler */ KE::KUbsan::HandleIntegerOverflow(Data, Lhs, Rhs); } /** * Handles the negate overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. * * @param Data * Supplies a pointer to the UBSAN overflow data. * * @param OldValue * Supplies old value. * * @return This routine does not return any value. * * @since XT 1.0 * * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 */ XTCLINK XTCDECL VOID __ubsan_handle_negate_overflow(IN PKUBSAN_OVERFLOW_DATA Data, IN ULONG_PTR OldValue) { /* Call UBSAN negate overflow handler */ KE::KUbsan::HandleNegateOverflow(Data, OldValue); } /** * Handles the out of bounds error. This is internal routine implementing ABI defined by CLANG UBSAN. * * @param Data * Supplies a pointer to the UBSAN out of bounds data. * * @param Index * Supplies an index operand. * * @return This routine does not return any value. * * @since XT 1.0 * * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 */ XTCLINK XTCDECL VOID __ubsan_handle_out_of_bounds(IN PKUBSAN_OUT_OF_BOUNDS_DATA Data, IN ULONG_PTR Index) { /* Call UBSAN out of bounds handler */ KE::KUbsan::HandleOutOfBounds(Data, Index); } /** * Handles the pointer overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. * * @param Data * Supplies a pointer to the UBSAN overflow data. * * @param Lhs * Supplies LHS operand. * * @param Rhs * Supplies RHS operand. * * @return This routine does not return any value. * * @since XT 1.0 * * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 */ XTCLINK XTCDECL VOID __ubsan_handle_pointer_overflow(IN PKUBSAN_OVERFLOW_DATA Data, IN ULONG_PTR Lhs, IN ULONG_PTR Rhs) { /* Call UBSAN pointer overflow handler */ KE::KUbsan::HandlePointerOverflow(Data, Lhs, Rhs); } /** * Handles the shift out of bounds error. This is internal routine implementing ABI defined by CLANG UBSAN. * * @param Data * Supplies a pointer to the UBSAN shift out of bounds data. * * @param Lhs * Supplies LHS operand. * * @param Rhs * Supplies RHS operand. * * @return This routine does not return any value. * * @since XT 1.0 * * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 */ XTCLINK XTCDECL VOID __ubsan_handle_shift_out_of_bounds(IN PKUBSAN_SHIFT_OUT_OF_BOUNDS_DATA Data, IN ULONG_PTR Lhs, IN ULONG_PTR Rhs) { /* Call UBSAN out of bounds handler */ KE::KUbsan::HandleShiftOutOfBounds(Data, Lhs, Rhs); } /** * Handles the subtraction overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. * * @param Data * Supplies a pointer to the UBSAN overflow data. * * @param Lhs * Supplies LHS operand. * * @param Rhs * Supplies RHS operand. * * @return This routine does not return any value. * * @since XT 1.0 * * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 */ XTCLINK XTCDECL VOID __ubsan_handle_sub_overflow(IN PKUBSAN_OVERFLOW_DATA Data, IN ULONG_PTR Lhs, IN ULONG_PTR Rhs) { /* Call UBSAN arithmetic overflow handler */ KE::KUbsan::HandleIntegerOverflow(Data, Lhs, Rhs); } /** * Handles the type mismatch error. This is internal routine implementing ABI defined by CLANG UBSAN. * * @param Data * Supplies a pointer to the UBSAN type mismatch data. * * @param Pointer * Supplies a pointer operand. * * @return This routine does not return any value. * * @since XT 1.0 * * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 */ XTCLINK XTCDECL VOID __ubsan_handle_type_mismatch(IN PKUBSAN_TYPE_MISMATCH_DATA Data, IN ULONG_PTR Pointer) { /* Call UBSAN type mismatch handler */ KE::KUbsan::HandleTypeMismatch(Data, Pointer); } /** * Handles the type mismatch error. This is internal routine implementing ABI defined by CLANG UBSAN. * * @param Data * Supplies a pointer to the UBSAN type mismatch data. * * @param Pointer * Supplies a pointer operand. * * @return This routine does not return any value. * * @since XT 1.0 * * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 */ XTCLINK XTCDECL VOID __ubsan_handle_type_mismatch_v1(IN PKUBSAN_TYPE_MISMATCH_DATA_V1 Data, IN ULONG_PTR Pointer) { KUBSAN_TYPE_MISMATCH_DATA MismatchData; /* Prepare UBSAN type mismatch data in old format */ MismatchData.Alignment = 1UL << Data->LogAlignment; MismatchData.Location = Data->Location; MismatchData.Type = Data->Type; MismatchData.TypeCheckKind = Data->TypeCheckKind; /* Call UBSAN type mismatch handler */ KE::KUbsan::HandleTypeMismatch(&MismatchData, Pointer); } ================================================ FILE: xtoskrnl/ke/runlevel.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/runlevel.cc * DESCRIPTION: Running Level management support * DEVELOPERS: Rafal Kupiec */ #include /** * Gets the current running level of the current processor. * * @return This routine returns the current running level. * * @since XT 1.0 */ XTFASTCALL KRUNLEVEL KE::RunLevel::GetCurrentRunLevel(VOID) { return HL::RunLevel::GetRunLevel(); } /** * Lowers the running level of the current processor. * * @param RunLevel * Supplies the new running level to lower to. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID KE::RunLevel::LowerRunLevel(IN KRUNLEVEL RunLevel) { KRUNLEVEL OldRunLevel; /* Read current run level */ OldRunLevel = HL::RunLevel::GetRunLevel(); /* Validate run level lowerage */ if(OldRunLevel > RunLevel) { /* Set new, lower run level */ HL::RunLevel::SetRunLevel(RunLevel); } } /** * Raises the running level of the current processor. * * @param RunLevel * Supplies the new running level to raise to. * * @return This routine returns the old running level. * * @since XT 1.0 */ XTFASTCALL KRUNLEVEL KE::RunLevel::RaiseRunLevel(IN KRUNLEVEL RunLevel) { KRUNLEVEL OldRunLevel; /* Read current run level */ OldRunLevel = HL::RunLevel::GetRunLevel(); /* Validate run level raise */ if(OldRunLevel < RunLevel) { /* Set new, higher run level */ HL::RunLevel::SetRunLevel(RunLevel); } /* Return old run level */ return OldRunLevel; } ================================================ FILE: xtoskrnl/ke/semphore.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/semphore.cc * DESCRIPTION: Semaphores support * DEVELOPERS: Rafal Kupiec */ #include /** * Initializes a kernel semaphore object. * * @param Semaphore * Supplies a pointer to a semaphore object. * * @param Count * Specifies the initial count value of the semaphore. * * @param Limit * Specifies a maximum count value of the semaphore. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID KE::Semaphore::InitializeSemaphore(IN PKSEMAPHORE Semaphore, IN LONG Count, IN LONG Limit) { /* Initialize semaphore header and limit */ Semaphore->Header.Type = SemaphoreObject; Semaphore->Header.SignalState = Count; Semaphore->Limit = Limit; /* Initialize semaphore wait list */ RTL::LinkedList::InitializeListHead(&Semaphore->Header.WaitListHead); } /** * Reads semaphore's current signal state. * * @param Semaphore * Supplies a pointer to a semaphore object. * * @return This routine returns the current signal state of the semaphore. * * @since XT 1.0 */ XTAPI LONG KE::Semaphore::ReadState(IN PKSEMAPHORE Semaphore) { /* Return semaphore's signal state */ return Semaphore->Header.SignalState; } /** * Releases a semaphore. * * @param Semaphore * Supplies a pointer to a semaphore object. * * @param Increment * Specifies the priority increment value of the semaphore. * * @param Adjustment * Specifies adjustment value added to the semaphore's initial count value. * * @param Wait * Determines whether release of the semaphore will be followed by a kernel wait routine call or not. * * @return This routine returns a previous signal state of the semaphore. * * @since NT 3.5 */ XTAPI LONG KE::Semaphore::ReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait) { UNIMPLEMENTED; return 0; } ================================================ FILE: xtoskrnl/ke/shdata.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/shdata.cc * DESCRIPTION: Kernel Shared Data * DEVELOPERS: Aiken Harris */ #include /** * Retrieves the current interrupt time using a lock-free read mechanism. * * @return This routine returns a LARGE_INTEGER containing the interrupt time. * * @since XT 1.0 */ XTAPI LARGE_INTEGER KE::SharedData::GetInterruptTime(VOID) { LARGE_INTEGER InterruptTime; /* Initialize to zero */ InterruptTime.QuadPart = 0; /* Perform a lock-free read sequence */ do { /* Read the primary high part and low part */ InterruptTime.HighPart = KernelSharedData->InterruptTime.High1Part; InterruptTime.LowPart = KernelSharedData->InterruptTime.LowPart; } while(InterruptTime.HighPart != KernelSharedData->InterruptTime.High2Part); /* Return the 64-bit time */ return InterruptTime; } /** * Retrieves a pointer to the memory-mapped Kernel Shared Data. * * @return This routine returns a pointer to the KSHARED_DATA structure. * * @since XT 1.0 */ XTAPI PKSHARED_DATA KE::SharedData::GetKernelSharedData(VOID) { /* Return the internally managed pointer */ return KernelSharedData; } /** * Retrieves the current system time using a lock-free read mechanism. * * @return This routine returns a LARGE_INTEGER containing the system time. * * @since XT 1.0 */ XTAPI LARGE_INTEGER KE::SharedData::GetSystemTime(VOID) { LARGE_INTEGER CurrentTime; /* Initialize to zero */ CurrentTime.QuadPart = 0; /* Perform a lock-free read sequence */ do { /* Read the primary high part and low part */ CurrentTime.HighPart = KernelSharedData->SystemTime.High1Part; CurrentTime.LowPart = KernelSharedData->SystemTime.LowPart; } while(CurrentTime.HighPart != KernelSharedData->SystemTime.High2Part); /* Return the 64-bit time */ return CurrentTime; } /** * Retrieves the global system tick count. * * @return This routine returns the current tick count. * * @since XT 1.0 */ XTAPI LARGE_INTEGER KE::SharedData::GetTickCount(VOID) { LARGE_INTEGER Ticks; /* Read the 64-bit tick count */ Ticks.QuadPart = (*(ULONGLONG*)&KernelSharedData->TickCount); /* Return the retrieved tick count */ return Ticks; } /** * Increments the global system tick count by one using a strict lock-free write mechanism. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::SharedData::IncrementTickCount() { LARGE_INTEGER Ticks; /* Increment tick count */ Ticks.QuadPart = (*(ULONGLONG*)&KernelSharedData->TickCount) + 1; /* Set the new tick count */ KernelSharedData->TickCount.High2Part = Ticks.HighPart; KernelSharedData->TickCount.LowPart = Ticks.LowPart; KernelSharedData->TickCount.High1Part = Ticks.HighPart; } /** * Maps and initializes the Kernel Shared Data (KSD) structure. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::SharedData::InitializeKernelSharedData(VOID) { PCSTR SourceString; XTSTATUS Status; /* Map Kernel Shared Data (KSD) */ Status = MM::Manager::MapKernelSharedData(); if(Status != STATUS_SUCCESS) { /* Failed to map KSD, raise kernel panic */ KE::Crash::Panic(0); } /* Bind the pointer to the architectural virtual address */ KernelSharedData = (PKSHARED_DATA)MM_KERNEL_SHARED_DATA_ADDRESS; /* Populate numeric version identifiers */ KernelSharedData->XtMajorVersion = XTOS_VERSION_MAJOR; KernelSharedData->XtMinorVersion = XTOS_VERSION_MINOR; /* Convert and copy system build string */ SourceString = XTOS_VERSION_BUILD; RTL::String::StringToWideString(KernelSharedData->XtBuild, (PCSTR*)&SourceString, (sizeof(KernelSharedData->XtBuild) / sizeof(WCHAR)) - 1); /* Convert and copy system build hash string */ SourceString = XTOS_VERSION_HASH; RTL::String::StringToWideString(KernelSharedData->XtBuildHash, (PCSTR*)&SourceString, (sizeof(KernelSharedData->XtBuildHash) / sizeof(WCHAR)) - 1); /* Convert and copy system architecture string */ SourceString = XTOS_VERSION_ARCH; RTL::String::StringToWideString(KernelSharedData->XtArchitecture, (PCSTR*)&SourceString, (sizeof(KernelSharedData->XtArchitecture) / sizeof(WCHAR)) - 1); /* Convert and copy system build date string */ SourceString = XTOS_VERSION_DATE; RTL::String::StringToWideString(KernelSharedData->XtDate, (PCSTR*)&SourceString, (sizeof(KernelSharedData->XtDate) / sizeof(WCHAR)) - 1); /* Convert and copy system build full date string */ SourceString = XTOS_VERSION_FULLDATE; RTL::String::StringToWideString(KernelSharedData->XtFullDate, (PCSTR*)&SourceString, (sizeof(KernelSharedData->XtFullDate) / sizeof(WCHAR)) - 1); } /** * Updates the global interrupt time using a strict lock-free write mechanism. * * @param Time * Supplies the new interrupt time as a 64-bit LARGE_INTEGER value. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::SharedData::SetInterruptTime(IN LARGE_INTEGER Time) { /* Set the new interrupt time */ KernelSharedData->InterruptTime.High2Part = Time.HighPart; KernelSharedData->InterruptTime.LowPart = Time.LowPart; KernelSharedData->InterruptTime.High1Part = Time.HighPart; } /** * Updates the global system time using a strict lock-free write mechanism. * * @param Time * Supplies the new system time as a 64-bit LARGE_INTEGER value. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::SharedData::SetSystemTime(IN LARGE_INTEGER Time) { /* Set the new system time */ KernelSharedData->SystemTime.High2Part = Time.HighPart; KernelSharedData->SystemTime.LowPart = Time.LowPart; KernelSharedData->SystemTime.High1Part = Time.HighPart; } ================================================ FILE: xtoskrnl/ke/spinlock.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/spinlock.cc * DESCRIPTION: Spinlocks support * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Acquires a specified queued spinlock. * * @param LockLevel * Supplies the queued spinlock level. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID KE::SpinLock::AcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_LEVEL LockLevel) { /* Acquire the queued spinlock */ AcquireSpinLock(KE::Processor::GetCurrentProcessorControlBlock()->LockQueue[LockLevel].Lock); } /** * Acquires a kernel spin lock. * * @param SpinLock * Supplies a pointer to the kernel spin lock. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID KE::SpinLock::AcquireSpinLock(IN OUT PKSPIN_LOCK SpinLock) { /* Try to acquire the lock */ while(RTL::Atomic::BitTestAndSet((PLONG)SpinLock, 0)) { /* Wait until locked is cleared */ while(*(VOLATILE PKSPIN_LOCK)SpinLock & 1) { /* Yield processor and keep waiting */ AR::CpuFunctions::YieldProcessor(); } } /* Add an explicit memory barrier */ AR::CpuFunctions::ReadWriteBarrier(); } /** * Initializes all kernel spinlocks. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::SpinLock::InitializeAllLocks() { /* Initialize all spin locks */ InitializeSpinLock(&DispatcherLockQueue); InitializeSpinLock(&PfnLockQueue); InitializeSpinLock(&SystemSpaceLockQueue); } /** * Initializes spinlock queues for current processor. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::SpinLock::InitializeLockQueues() { PKPROCESSOR_CONTROL_BLOCK ControlBlock; /* Get current processor control block */ ControlBlock = KE::Processor::GetCurrentProcessorControlBlock(); /* Initialize PCB lock queues */ ControlBlock->LockQueue[DispatcherLock].Lock = &DispatcherLockQueue; ControlBlock->LockQueue[DispatcherLock].Next = NULLPTR; ControlBlock->LockQueue[ExpansionLock].Lock = &ExpansionLockQueue; ControlBlock->LockQueue[ExpansionLock].Next = NULLPTR; ControlBlock->LockQueue[PfnLock].Lock = &PfnLockQueue; ControlBlock->LockQueue[PfnLock].Next = NULLPTR; ControlBlock->LockQueue[SystemSpaceLock].Lock = &SystemSpaceLockQueue; ControlBlock->LockQueue[SystemSpaceLock].Next = NULLPTR; ControlBlock->LockQueue[VacbLock].Lock = &VacbLockQueue; ControlBlock->LockQueue[VacbLock].Next = NULLPTR; ControlBlock->LockQueue[MasterLock].Lock = &MasterLockQueue; ControlBlock->LockQueue[MasterLock].Next = NULLPTR; ControlBlock->LockQueue[NonPagedAllocPoolLock].Lock = &NonPagedAllocLockQueue; ControlBlock->LockQueue[NonPagedAllocPoolLock].Next = NULLPTR; ControlBlock->LockQueue[IoCancelLock].Lock = &IoCancelLockQueue; ControlBlock->LockQueue[IoCancelLock].Next = NULLPTR; ControlBlock->LockQueue[WorkQueueLock].Lock = &WorkLockQueue; ControlBlock->LockQueue[WorkQueueLock].Next = NULLPTR; ControlBlock->LockQueue[IoVpbLock].Lock = &IoVpbLockQueue; ControlBlock->LockQueue[IoVpbLock].Next = NULLPTR; ControlBlock->LockQueue[IoDatabaseLock].Lock = &IoDatabaseLockQueue; ControlBlock->LockQueue[IoDatabaseLock].Next = NULLPTR; ControlBlock->LockQueue[IoCompletionLock].Lock = &IoCompletionLockQueue; ControlBlock->LockQueue[IoCompletionLock].Next = NULLPTR; ControlBlock->LockQueue[FileSystemLock].Lock = &FileSystemLockQueue; ControlBlock->LockQueue[FileSystemLock].Next = NULLPTR; ControlBlock->LockQueue[AfdWorkQueueLock].Lock = NULLPTR; ControlBlock->LockQueue[AfdWorkQueueLock].Next = NULLPTR; ControlBlock->LockQueue[BcbLock].Lock = NULLPTR; ControlBlock->LockQueue[BcbLock].Next = NULLPTR; ControlBlock->LockQueue[NonPagedPoolLock].Lock = &NonPagedPoolLockQueue; ControlBlock->LockQueue[NonPagedPoolLock].Next = NULLPTR; ControlBlock->LockQueue[ReservedSystemLock].Lock = NULLPTR; ControlBlock->LockQueue[ReservedSystemLock].Next = NULLPTR; ControlBlock->LockQueue[TimerTableLock].Lock = &TimerTableLockQueue; ControlBlock->LockQueue[TimerTableLock].Next = NULLPTR; } /** * Initializes a kernel spinlock object. * * @param SpinLock * Supplies a pointer to a kernel spin lock. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID KE::SpinLock::InitializeSpinLock(IN PKSPIN_LOCK SpinLock) { /* Zero initialize spinlock */ *SpinLock = 0; } /** * Releases a queued spinlock. * * @param LockLevel * Supplies the queued spinlock level. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID KE::SpinLock::ReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_LEVEL LockLevel) { /* Clear the lock */ ReleaseSpinLock(KE::Processor::GetCurrentProcessorControlBlock()->LockQueue[LockLevel].Lock); } /** * Releases a kernel spin lock. * * @param SpinLock * Supplies a pointer to the kernel spin lock. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID KE::SpinLock::ReleaseSpinLock(IN OUT PKSPIN_LOCK SpinLock) { /* Clear the lock */ RTL::Atomic::And32((PLONG)SpinLock, 0); /* Add an explicit memory barrier */ AR::CpuFunctions::ReadWriteBarrier(); } /** * Tests a kernel spin lock. * * @param SpinLock * Supplies a pointer to the kernel spin lock. * * @return This routine returns TRUE if the lock is free, FALSE otherwise. * * @since XT 1.0 */ XTFASTCALL BOOLEAN TestSpinLock(IN PKSPIN_LOCK SpinLock) { /* Check if the lock is free */ if(*SpinLock) { /* Spinlock is busy, yield processor and return FALSE */ AR::CpuFunctions::YieldProcessor(); return FALSE; } /* Spinlock is free, return TRUE */ return TRUE; } ================================================ FILE: xtoskrnl/ke/sysres.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/sysres.cc * DESCRIPTION: System resources management; This code is based on the MinocaOS implementation * DEVELOPERS: Rafal Kupiec */ #include /** * Looks for an unacquired system resource of the specified type and acquires it. * * @param ResourceType * Supplies system resource type. * * @param ResourceHeader * Specifies a memory area where a pointer to the system resource header will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS KE::SystemResources::AcquireResource(IN SYSTEM_RESOURCE_TYPE ResourceType, OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader) { /* Get system resource and acquire an ownership */ return GetSystemResource(ResourceType, TRUE, ResourceHeader); } /** * Looks for an unacquired system resource of the specified type. * * @param ResourceType * Supplies system resource type. * * @param Acquire * Specifies whether system resource should be acquired or not. * * @param ResourceHeader * Specifies a memory area where a pointer to the system resource header will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI XTSTATUS KE::SystemResources::GetSystemResource(IN SYSTEM_RESOURCE_TYPE ResourceType, IN BOOLEAN ResourceLock, OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader) { PSYSTEM_RESOURCE_HEADER Resource; PLIST_ENTRY ListEntry; BOOLEAN Interrupts; XTSTATUS Status; /* Assume resource found successfully */ Status = STATUS_SUCCESS; /* Check if interrupts are enabled */ Interrupts = AR::CpuFunctions::InterruptsEnabled(); /* Disable interrupts and acquire a spinlock */ AR::CpuFunctions::ClearInterruptFlag(); KE::SpinLock::AcquireSpinLock(&ResourcesLock); /* Iterate through system resources list */ ListEntry = ResourcesListHead.Flink; while(ListEntry != &ResourcesListHead) { /* Get resource header */ Resource = CONTAIN_RECORD(ListEntry, SYSTEM_RESOURCE_HEADER, ListEntry); /* Check if resource type matches */ if(Resource->ResourceType == ResourceType) { /* Check if resource is locked */ if(Resource->ResourceLocked) { /* Resource locked, set status code and stop browsing a list */ Status = STATUS_RESOURCE_LOCKED; break; } /* Check if resource lock should be acquired */ if(ResourceLock) { /* Acquire resource lock */ Resource->ResourceLocked = TRUE; } /* Stop browsing a list */ break; } /* Go to the next list entry */ ListEntry = ListEntry->Flink; } /* Check if resource was found */ if(ListEntry == &ResourcesListHead) { /* Resource not found, return NULLPTR */ Resource = NULLPTR; Status = STATUS_NOT_FOUND; } /* Release spinlock and re-enable interrupts if necessary */ KE::SpinLock::ReleaseSpinLock(&ResourcesLock); if(Interrupts) { /* Re-enable interrupts */ AR::CpuFunctions::SetInterruptFlag(); } /* Return resource header and status code */ *ResourceHeader = Resource; return Status; } /** * Looks for an unacquired system resource of the specified type and returns it without acquiring an ownership. * * @param ResourceType * Supplies system resource type. * * @param ResourceHeader * Specifies a memory area where a pointer to the system resource header will be stored. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS KE::SystemResources::GetResource(IN SYSTEM_RESOURCE_TYPE ResourceType, OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader) { /* Get system resource without acquiring an ownership */ return GetSystemResource(ResourceType, FALSE, ResourceHeader); } /** * Initializes system resource management. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI VOID KE::SystemResources::InitializeResources(VOID) { PSYSTEM_RESOURCE_HEADER ResourceHeader; PLIST_ENTRY ListEntry, NextListEntry; ULONG ResourceSize; /* Initialize system resources spin lock and resource list */ KE::SpinLock::InitializeSpinLock(&ResourcesLock); RTL::LinkedList::InitializeListHead(&ResourcesListHead); /* Make sure there are some system resources available */ if(!RTL::LinkedList::ListEmpty(KE::BootInformation::GetSystemResources())) { /* Iterate through system resources list */ ListEntry = KE::BootInformation::GetSystemResources()->Flink; while(ListEntry != KE::BootInformation::GetSystemResources()) { /* Get resource header and next list entry */ ResourceHeader = CONTAIN_RECORD(ListEntry, SYSTEM_RESOURCE_HEADER, ListEntry); NextListEntry = ListEntry->Flink; /* Basic resource type validation */ switch(ResourceHeader->ResourceType) { case SystemResourceAcpi: /* ACPI system resource */ ResourceSize = sizeof(SYSTEM_RESOURCE_ACPI); break; case SystemResourceFrameBuffer: /* FrameBuffer system resource */ ResourceSize = sizeof(SYSTEM_RESOURCE_FRAMEBUFFER); break; default: /* Unknown system resource type, skip it */ ResourceSize = 0; break; } /* Validate resource size */ if(ResourceSize != 0 && ResourceSize == ResourceHeader->ResourceSize) { /* Move valid resource to the internal kernel list of system resources */ RTL::LinkedList::RemoveEntryList(&ResourceHeader->ListEntry); RTL::LinkedList::InsertTailList(&ResourcesListHead, &ResourceHeader->ListEntry); } /* Go to the next list entry */ ListEntry = NextListEntry; } } } /** * Releases boot system resource. * * @param ResourceHeader * Specifies a pointer to the boot system resource header. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::SystemResources::ReleaseResource(IN PSYSTEM_RESOURCE_HEADER ResourceHeader) { /* Disable interrupts and acquire a spinlock */ AR::CpuFunctions::ClearInterruptFlag(); KE::SpinLock::AcquireSpinLock(&ResourcesLock); /* Release resource lock */ ResourceHeader->ResourceLocked = FALSE; /* Release spinlock and enable interrupts */ KE::SpinLock::ReleaseSpinLock(&ResourcesLock); AR::CpuFunctions::SetInterruptFlag(); } ================================================ FILE: xtoskrnl/ke/systime.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/systime.cc * DESCRIPTION: Timebase and system clock support * DEVELOPERS: Aiken Harris */ #include /** * Returns the current system time. * * @param SystemTime * Supplies a pointer to a variable that receives the current system time. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::SystemTime::GetSystemTime(OUT PLARGE_INTEGER SystemTime) { LARGE_INTEGER CurrentTime; /* Fetch the time using the lock-free shared data mechanism and return it */ CurrentTime = KE::SharedData::GetSystemTime(); SystemTime->QuadPart = CurrentTime.QuadPart; } /** * Sets the system time, updates the boot time, and optionally updates the hardware Real-Time Clock (RTC). * * @param NewTime * Supplies a pointer to the new system time. * * @param OldTime * Supplies a pointer to a variable that receives the previous system time. * * @param CorrectInterruptTime * Specifies if the physical interrupt time should be corrected. * * @param WriteToRtc * Specifies if the new system time should be written to RTC. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::SystemTime::SetSystemTime(IN PLARGE_INTEGER NewTime, OUT PLARGE_INTEGER OldTime, IN BOOLEAN CorrectInterruptTime, IN BOOLEAN WriteToRtc) { LARGE_INTEGER TimeDelta; TIME_FIELDS TimeFields; /* Check if the new system time should be written to the RTC */ if(WriteToRtc) { /* Convert the new system time to a human-readable calendar structure */ RTL::Time::XtEpochToTimeFields(NewTime, &TimeFields); } /* Start a guarded code block */ { /* Raise runlevel to HIGH level */ KE::RaiseRunLevel Runlevel(HIGH_LEVEL); /* Save the previous system time for the caller and for delta calculation */ GetSystemTime(OldTime); /* Write new system time to the Kernel Shared Data */ KE::SharedData::SetSystemTime(*NewTime); /* Check if the new system time should be written to the RTC */ if(WriteToRtc) { /* Update the hardware CMOS clock */ HL::Rtc::SetRealTimeClock(&TimeFields); } /* Calculate the time difference */ TimeDelta.QuadPart = NewTime->QuadPart - OldTime->QuadPart; /* Update the boot time by the delta */ BootTime.QuadPart += TimeDelta.QuadPart; } /* Check if interrupt time needs to be corrected */ if(CorrectInterruptTime) { UNIMPLEMENTED; } } /** * Sets the maximum and minimum time increment values in 100ns units. * * @param MinIncrement * Supplies the minimum time increment. * * @param MaxIncrement * Supplies the maximum time increment. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::SystemTime::SetTimeIncrement(IN ULONG MinIncrement, IN ULONG MaxIncrement) { /* Store resolution boundaries while enforcing a 1ms architectural floor */ MaximumIncrement = MaxIncrement; MinimumIncrement = MAX(MinIncrement, 10000); /* Set the tick offset to the maximum increment */ TickOffset = (LONG)MaxIncrement; /* Set the default time adjustment to the full tick period */ TimeAdjustment = MaxIncrement; } /** * Services the periodic clock interrupt by advancing the global interrupt time, detecting full * system tick boundaries via the tick offset accumulator, and advancing the wall-clock system time. * * @param TrapFrame * Supplies a pointer to the hardware trap frame representing the interrupted execution context. * * @param Increment * Supplies the calibrated time delta for this hardware interrupt in 100-nanosecond units. * * @param RunLevel * Supplies the system run level at which the interrupt was taken. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID KE::SystemTime::UpdateSystemTime(IN PKTRAP_FRAME TrapFrame, IN ULONG Increment, IN KRUNLEVEL RunLevel) { LARGE_INTEGER InterruptTime, SystemTime; LONG CurrentTickOffset; /* Advance the global interrupt time on every hardware tick */ InterruptTime = KE::SharedData::GetInterruptTime(); InterruptTime.QuadPart += Increment; KE::SharedData::SetInterruptTime(InterruptTime); /* Atomically consume the current tick budget and retrieve the pre-decrement value */ CurrentTickOffset = RTL::Atomic::ExchangeAdd32((PLONG)&TickOffset, -(LONG)Increment); /* Determine whether the accumulated increments have crossed the full tick boundary */ if(CurrentTickOffset <= (LONG)Increment) { /* A full system tick has elapsed, advance the wall-clock time by the configured adjustment */ SystemTime = KE::SharedData::GetSystemTime(); SystemTime.QuadPart += TimeAdjustment; KE::SharedData::SetSystemTime(SystemTime); /* Update the tick count */ KE::SharedData::IncrementTickCount(); /* Reload the tick offset accumulator for the next full tick period */ TickOffset += MaximumIncrement; /* Update processor and thread runtime accounting */ KE::Dispatcher::UpdateRunTime(TrapFrame, RunLevel); } } ================================================ FILE: xtoskrnl/ke/timer.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/ke/timer.cc * DESCRIPTION: Kernel timer object support * DEVELOPERS: Rafal Kupiec */ #include /** * Cancels the timer. * * @param Timer * Supplies a pointer to a timer object. * * @return This routine returns TRUE if the cancelled timer was set, or FALSE otherwise. * * @since NT 3.5 */ XTAPI BOOLEAN KE::Timer::CancelTimer(IN PKTIMER Timer) { BOOLEAN Result; KRUNLEVEL RunLevel; /* Set default result value */ Result = FALSE; /* Raise run level and acquire dispatcher lock */ RunLevel = KE::RunLevel::RaiseRunLevel(SYNC_LEVEL); KE::SpinLock::AcquireQueuedSpinLock(DispatcherLock); /* Check timer status */ if(Timer->Header.Inserted) { /* Remove the timer from the list */ RemoveTimer(Timer); Result = TRUE; } /* Release dispatcher lock and process the deferred ready list */ KE::SpinLock::ReleaseQueuedSpinLock(DispatcherLock); KE::Dispatcher::ExitDispatcher(RunLevel); /* Return result */ return Result; } /** * Clears the signal state of the timer. * * @param Timer * Supplies a pointer to a timer object. * * @return This routine does not return any value. * * @since NT 4.0 */ XTAPI VOID KE::Timer::ClearTimer(IN PKTIMER Timer) { /* Clear signal state */ Timer->Header.SignalState = 0; } /** * Reads the current signal state of the given timer. * * @param Timer * Supplies a pointer to a timer object. * * @return This routine returns TRUE if the timer is set, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN KE::Timer::GetState(IN PKTIMER Timer) { /* Return timer state */ return (BOOLEAN)Timer->Header.SignalState; } /** * Initializes an extended kernel timer. * * @param Timer * Supplies a pointer to a timer object. * * @param Type * Supplies the type of the timer. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::Timer::InitializeTimer(OUT PKTIMER Timer, IN KTIMER_TYPE Type) { /* Initialize the header */ Timer->Header.Type = TimerNotificationObject + (UCHAR)Type; Timer->Header.Inserted = 0; Timer->Header.SignalState = 0; /* Initialize the timer data */ Timer->DueTime.QuadPart = 0; Timer->Period = 0; /* Initialize linked lists */ RTL::LinkedList::InitializeListHead(&Timer->Header.WaitListHead); RTL::LinkedList::InitializeListHead(&Timer->TimerListEntry); } /** * Queries the timer's interrupt due time. * * @param Timer * Supplies a pointer to a timer object. * * @return This routine returns the time remaining on the timer, or 0 if the timer is not set. * * @since XT 1.0 */ XTAPI ULONGLONG KE::Timer::QueryTimer(IN PKTIMER Timer) { KRUNLEVEL RunLevel; ULONGLONG DueTime; /* Set initial due time */ DueTime = 0; /* Raise run level and acquire dispatcher lock */ RunLevel = KE::RunLevel::RaiseRunLevel(SYNC_LEVEL); KE::SpinLock::AcquireQueuedSpinLock(DispatcherLock); /* Check timer status */ if(Timer->Header.Inserted) { /* Get timer's due time */ DueTime = Timer->DueTime.QuadPart; } /* Release dispatcher lock and process the deferred ready list */ KE::SpinLock::ReleaseQueuedSpinLock(DispatcherLock); KE::Dispatcher::ExitDispatcher(RunLevel); /* Return timer's due time */ return DueTime; } /** * Sets the supplied timer to expire at the specified time. * * @param Timer * Supplies a pointer to a timer object. * * @param DueTime * Supplies the time at which the timer should expire (both absolute and relative times are supported). * * @param Period * Supplies the timer period. * * @param Dpc * Supplies a pointer to a Deferred Procedure Call (DPC) object. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::Timer::SetTimer(IN PKTIMER Timer, IN LARGE_INTEGER DueTime, IN LONG Period, IN PKDPC Dpc) { UNIMPLEMENTED; } /** * Removes a specified timer from the timer list. * * @param Timer * Supplies a pointer to a timer object. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID KE::Timer::RemoveTimer(IN OUT PKTIMER Timer) { /* Remove the timer from the list */ Timer->Header.Inserted = FALSE; RTL::LinkedList::RemoveEntryList(&Timer->TimerListEntry); } ================================================ FILE: xtoskrnl/mm/alloc.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/alloc.cc * DESCRIPTION: Memory Manager pool allocator * DEVELOPERS: Aiken Harris */ #include /** * Allocates pages from the non-paged pool. * * @param Pages * Specifies the number of pages to allocate. * * @param Memory * Supplies a pointer to the allocated pool of pages. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Allocator::AllocateNonPagedPoolPages(IN PFN_COUNT Pages, OUT PVOID *Memory) { PMMPTE CurrentPte, PointerPte, ValidPte; PLIST_ENTRY Entry, LastHead, ListHead; PMMFREE_POOL_ENTRY FreePage; PFN_NUMBER PageFrameNumber; PVOID BaseAddress; ULONG Index; PMMPFN Pfn; /* Calculate the free list index based on the requested page count, capped at the maximum list head index */ Index = MIN(Pages, MM_MAX_FREE_PAGE_LIST_HEADS) - 1; /* Set the starting list head and the boundary for the search loop */ ListHead = &NonPagedPoolFreeList[Index]; LastHead = &NonPagedPoolFreeList[MM_MAX_FREE_PAGE_LIST_HEADS]; /* Start a guarded code block */ { /* Acquire the Non-Paged pool lock and raise runlevel to DISPATCH level */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::QueuedSpinLockGuard NonPagedPoolSpinLock(NonPagedPoolLock); /* Iterate through the free lists */ do { /* Iterate through the free entries in the current list */ Entry = ListHead->Flink; while(Entry != ListHead) { /* Get the free pool entry structure from the list entry */ FreePage = CONTAIN_RECORD(Entry, MMFREE_POOL_ENTRY, List); /* Check if this block is large enough to satisfy the request */ if(FreePage->Size >= Pages) { /* Adjust the size of the free block to account for the allocated pages */ FreePage->Size -= Pages; /* Calculate the base address of the allocated block */ BaseAddress = (PVOID)((ULONG_PTR)FreePage + (FreePage->Size << MM_PAGE_SHIFT)); /* Remove the entry from the free list */ RTL::LinkedList::RemoveEntryList(&FreePage->List); /* Check if there is remaining space in the entry */ if(FreePage->Size != 0) { /* Calculate the new list index for the remaining fragment */ Index = MIN(FreePage->Size, MM_MAX_FREE_PAGE_LIST_HEADS) - 1; /* Insert the entry into the free list */ RTL::LinkedList::InsertTailList(&NonPagedPoolFreeList[Index], &FreePage->List); } /* Get the PTE for the allocated address */ PointerPte = MM::Paging::GetPteAddress(BaseAddress); /* Get the PFN database entry for the corresponding physical page */ Pfn = MM::Pfn::GetPfnEntry(MM::Paging::GetPageFrameNumber(PointerPte)); /* Denote allocation boundaries */ Pfn->u3.e1.ReadInProgress = 1; /* Check if multiple pages were requested */ if(Pages != 1) { /* Advance to the PTE of the last page in the allocation */ PointerPte = MM::Paging::AdvancePte(PointerPte, Pages - 1); /* Get the PFN entry for the last page */ Pfn = MM::Pfn::GetPfnEntry(MM::Paging::GetPageFrameNumber(PointerPte)); } /* Denote allocation boundaries */ Pfn->u3.e1.WriteInProgress = 1; /* Set the allocated memory address and return success */ *Memory = BaseAddress; return STATUS_SUCCESS; } /* Move to the next entry in the free list */ Entry = FreePage->List.Flink; } } while(++ListHead < LastHead); } /* No suitable free block found; try to expand the pool by reserving system PTEs */ PointerPte = MM::Pte::ReserveSystemPtes(Pages, NonPagedPoolExpansion); if(PointerPte == NULLPTR) { /* PTE reservation failed, return insufficient resources */ return STATUS_INSUFFICIENT_RESOURCES; } /* Acquire the Non-Paged pool lock and raise runlevel to DISPATCH level */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::QueuedSpinLockGuard NonPagedPoolSpinLock(NonPagedPoolLock); /* Acquire the PFN database lock */ KE::QueuedSpinLockGuard PfnSpinLock(PfnLock); /* Check if there are enough available physical pages to back the allocation */ if(Pages >= MM::Pfn::GetAvailablePages()) { /* Not enough physical pages, release the reserved system PTEs */ MM::Pte::ReleaseSystemPtes(PointerPte, Pages, NonPagedPoolExpansion); /* Return failure due to insufficient resources */ return STATUS_INSUFFICIENT_RESOURCES; } /* Set the tracking pointer to iterate through the reserved PTE space */ CurrentPte = PointerPte; /* Get a template valid PTE and loop through the allocation to map physical pages */ ValidPte = MM::Pte::GetValidPte(); do { /* Allocate a physical page */ PageFrameNumber = MM::Pfn::AllocatePhysicalPage(MM::Colors::GetNextColor()); /* Initialize the PFN entry for the allocated physical page */ Pfn = MM::Pfn::GetPfnEntry(PageFrameNumber); MM::Paging::SetPte(&Pfn->OriginalPte, 0, MM_READWRITE << MM_PROTECT_FIELD_SHIFT); Pfn->PteAddress = CurrentPte; Pfn->u2.ShareCount = 1; Pfn->u3.e1.PageLocation = ActiveAndValid; Pfn->u3.e2.ReferenceCount = 1; Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress(CurrentPte)); /* Build a valid PTE pointing to the allocated page frame */ MM::Paging::SetPte(ValidPte, PageFrameNumber, 0); /* Write the valid PTE into the system PTE range and advance to the next PTE */ *CurrentPte = *ValidPte; CurrentPte = MM::Paging::GetNextPte(CurrentPte); } while(--Pages > 0); /* Dnote allocation boundaries */ Pfn->u3.e1.WriteInProgress = 1; /* Get the PFN entry for the first page of the allocation */ Pfn = MM::Pfn::GetPfnEntry(MM::Paging::GetPageFrameNumber(PointerPte)); /* Denote allocation boundaries */ Pfn->u3.e1.ReadInProgress = 1; /* Convert the PTE address to the virtual address and store in the buffer */ *Memory = MM::Paging::GetPteVirtualAddress(PointerPte); /* Return success */ return STATUS_SUCCESS; } /** * Allocates pages from the paged pool. * * @param Pages * Specifies the number of pages to allocate. * * @param Memory * Supplies a pointer to the allocated pool of pages. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Allocator::AllocatePagedPoolPages(IN PFN_COUNT Pages, OUT PVOID *Memory) { UNIMPLEMENTED; /* Return not implemented status code */ return STATUS_NOT_IMPLEMENTED; } /** * Allocates pages from the specified pool type. * * @param PoolType * Specifies the type of pool to allocate pages from. * * @param Bytes * Specifies the number of bytes to allocate. * * @param Memory * Supplies a pointer to the allocated pool of pages. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Allocator::AllocatePages(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, OUT PVOID *Memory) { PFN_COUNT Pages; /* Initialize the output parameter */ *Memory = NULLPTR; /* Convert bytes to pages */ Pages = SIZE_TO_PAGES(Bytes); /* Check if there are any pages to allocate */ if(!Pages) { /* Nothing to allocate, return NULLPTR */ return STATUS_INVALID_PARAMETER; } /* Switch on pool type */ switch(PoolType & MM_POOL_TYPE_MASK) { case NonPagedPool: /* Allocate non-paged pool */ return AllocateNonPagedPoolPages(Pages, Memory); case PagedPool: /* Allocate paged pool */ return AllocatePagedPoolPages(Pages, Memory); } /* Invalid pool type specified, return error */ return STATUS_INVALID_PARAMETER; } /** * Allocates a block of memory from the specified pool type. * * @param PoolType * Specifies the type of pool to allocate from. * * @param Bytes * Specifies the number of bytes to allocate. * * @param Memory * Supplies a pointer to the allocated memory. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Allocator::AllocatePool(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, OUT PVOID *Memory) { /* Allocate pool */ return AllocatePool(PoolType, Bytes, Memory, SIGNATURE32('N', 'o', 'n', 'e')); } /** * Allocates a block of memory from the specified pool type. * * @param PoolType * Specifies the type of pool to allocate from. * * @param Bytes * Specifies the number of bytes to allocate. * * @param Memory * Supplies a pointer to the allocated memory. * * @param Tag * Specifies the allocation identifying tag. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Allocator::AllocatePool(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, OUT PVOID *Memory, IN ULONG Tag) { PPOOL_HEADER PoolEntry, NextPoolEntry, PoolRemainder; PPOOL_DESCRIPTOR PoolDescriptor; USHORT BlockSize, Index; PLIST_ENTRY ListHead; XTSTATUS Status; /* Verify run level for the specified pool */ VerifyRunLevel(PoolType, Bytes, NULLPTR); /* Check if there are any bytes to allocate */ if(!Bytes) { /* Allocate at least a single byte */ Bytes = 1; } /* Retrieve the specific pool descriptor based on the masked pool type */ PoolDescriptor = PoolVector[PoolType & MM_POOL_TYPE_MASK]; /* Determine if the requested size exceeds the maximum standard pool block capacity */ if(Bytes > (MM_PAGE_SIZE - (sizeof(POOL_HEADER) + MM_POOL_BLOCK_SIZE))) { /* Allocate new, raw pages directly to satisfy the large allocation request */ Status = AllocatePages(PoolType, Bytes, (PVOID*)&PoolEntry); if(Status != STATUS_SUCCESS || !PoolEntry) { /* Allocation failed, clear the output pointer and return the error status */ *Memory = NULLPTR; return Status; } /* Update the pool descriptor statistical counters */ RTL::Atomic::ExchangeAdd32((PLONG)&PoolDescriptor->TotalBigAllocations, (LONG)SIZE_TO_PAGES(Bytes)); RTL::Atomic::ExchangeAdd64((PLONG_PTR)&PoolDescriptor->TotalBytes, (LONG_PTR)Bytes); RTL::Atomic::Increment32((PLONG)&PoolDescriptor->RunningAllocations); /* Attempt to register the big allocation within the tracking table */ if(!RegisterBigAllocationTag(PoolEntry, Tag, (ULONG)SIZE_TO_PAGES(Bytes), PoolType)) { /* Fallback to a default tag */ Tag = SIGNATURE32('B', 'i', 'g', 'A'); } /* Register the allocation in the tracking table */ RegisterAllocationTag(Tag, SIZE_TO_PAGES(Bytes), PoolType); /* Supply the allocated address and return success */ *Memory = PoolEntry; return STATUS_SUCCESS; } /* Calculate the required block index */ Index = (USHORT)((Bytes + sizeof(POOL_HEADER) + (MM_POOL_BLOCK_SIZE - 1)) / MM_POOL_BLOCK_SIZE); /* Resolve the appropriate list head for the calculated block index */ ListHead = &PoolDescriptor->ListHeads[Index]; while(ListHead != &PoolDescriptor->ListHeads[MM_POOL_LISTS_PER_PAGE]) { /* Check whether the target free list contains available blocks */ if(!PoolListEmpty(ListHead)) { /* Start a guarded code block */ { /* Acquire the pool lock */ PoolLockGuard PoolLock((MMPOOL_TYPE)(PoolDescriptor->PoolType & MM_POOL_TYPE_MASK)); /* Re-evaluate the list emptiness to prevent race conditions */ if(PoolListEmpty(ListHead)) { /* Proceed to evaluate the next list head */ continue; } /* Validate the structural integrity of the pool list */ VerifyPoolLinks(ListHead); /* Extract the first available free block from the list and resolve its header */ PoolEntry = GetPoolEntry(RemovePoolHeadList(ListHead)); /* Re-validate the pool list and verify integrity of the extracted block */ VerifyPoolLinks(ListHead); VerifyPoolBlocks(PoolEntry); /* Check whether the extracted block requires splitting */ if(PoolEntry->BlockSize != Index) { /* Check if the block is located at the absolute beginning of a page */ if(PoolEntry->PreviousSize == 0) { /* Split the block and initialize the remainder */ PoolRemainder = GetPoolBlock(PoolEntry, Index); PoolRemainder->BlockSize = PoolEntry->BlockSize - Index; PoolRemainder->PreviousSize = Index; /* Resolve the subsequent block and update its previous size field */ NextPoolEntry = GetPoolNextBlock(PoolRemainder); if(PAGE_ALIGN(NextPoolEntry) != NextPoolEntry) { /* Adjust the adjacent block to reflect the new size of the remainder */ NextPoolEntry->PreviousSize = PoolRemainder->BlockSize; } } else { /* Split the extracted block */ PoolRemainder = PoolEntry; PoolEntry->BlockSize -= Index; /* Advance the pointer to the new block and update its previous size */ PoolEntry = GetPoolNextBlock(PoolEntry); PoolEntry->PreviousSize = PoolRemainder->BlockSize; /* Resolve the adjacent next block and adjust its previous size */ NextPoolEntry = GetPoolBlock(PoolEntry, Index); if(PAGE_ALIGN(NextPoolEntry) != NextPoolEntry) { /* Adjust the adjacent block */ NextPoolEntry->PreviousSize = Index; } } /* Finalize the structural sizing fields */ BlockSize = PoolRemainder->BlockSize; PoolEntry->BlockSize = Index; PoolRemainder->PoolType = 0; /* Validate the target free list */ VerifyPoolLinks(&PoolDescriptor->ListHeads[BlockSize - 1]); /* Ensure the remainder block is large enough to contain valid list */ if(BlockSize != 1) { /* Insert the new remainder block into the appropriate free list and verify links */ InsertPoolTailList(&PoolDescriptor->ListHeads[BlockSize - 1], GetPoolFreeBlock(PoolRemainder)); VerifyPoolLinks(GetPoolFreeBlock(PoolRemainder)); } } /* Update the active pool type and verify structural invariants */ PoolEntry->PoolType = PoolType + 1; VerifyPoolBlocks(PoolEntry); } /* Update the pool descriptor statistical counters */ RTL::Atomic::ExchangeAdd64((PLONG_PTR)&PoolDescriptor->TotalBytes, (LONG_PTR)(PoolEntry->BlockSize * MM_POOL_BLOCK_SIZE)); RTL::Atomic::Increment32((PLONG)&PoolDescriptor->RunningAllocations); /* Register the allocation in the tracking table */ RegisterAllocationTag(Tag, PoolEntry->BlockSize * MM_POOL_BLOCK_SIZE, PoolType); /* Assign the specified identification tag */ PoolEntry->PoolTag = Tag; /* Clear the internal list links */ (GetPoolFreeBlock(PoolEntry))->Flink = NULLPTR; (GetPoolFreeBlock(PoolEntry))->Blink = NULLPTR; /* Supply the allocated address and return success */ *Memory = GetPoolFreeBlock(PoolEntry); return STATUS_SUCCESS; } /* Advance to the next list head */ ListHead++; } /* Allocate a new page to fulfill the request */ Status = AllocatePages(PoolType, MM_PAGE_SIZE, (PVOID *)&PoolEntry); if(Status != STATUS_SUCCESS || !PoolEntry) { /* Allocation failed, clear the output pointer and return the error status */ *Memory = NULLPTR; return Status; } /* Initialize the structural header */ PoolEntry->Long = 0; PoolEntry->BlockSize = Index; PoolEntry->PoolType = PoolType + 1; /* Calculate the block size of the remaining unused space */ BlockSize = (MM_PAGE_SIZE / MM_POOL_BLOCK_SIZE) - Index; /* Initialize the remainder entry representing the free space */ PoolRemainder = GetPoolBlock(PoolEntry, Index); PoolRemainder->Long = 0; PoolRemainder->BlockSize = BlockSize; PoolRemainder->PreviousSize = Index; /* Update the pool descriptor statistical counters */ RTL::Atomic::Increment32((PLONG)&PoolDescriptor->TotalPages); RTL::Atomic::ExchangeAdd64((PLONG_PTR)&PoolDescriptor->TotalBytes, (LONG_PTR)(PoolEntry->BlockSize * MM_POOL_BLOCK_SIZE)); /* Check if the remainder block is large enough */ if(PoolRemainder->BlockSize != 1) { /* Acquire the pool lock */ PoolLockGuard PoolLock((MMPOOL_TYPE)(PoolDescriptor->PoolType & MM_POOL_TYPE_MASK)); /* Validate the target free list structure */ VerifyPoolLinks(&PoolDescriptor->ListHeads[BlockSize - 1]); /* Insert the remainder block into the free list */ InsertPoolTailList(&PoolDescriptor->ListHeads[BlockSize - 1], GetPoolFreeBlock(PoolRemainder)); /* Verify the structural integrity of the remainder and the allocated blocks */ VerifyPoolLinks(GetPoolFreeBlock(PoolRemainder)); VerifyPoolBlocks(PoolEntry); } else { /* Verify the allocated block invariants */ VerifyPoolBlocks(PoolEntry); } /* Increment the running allocation counter for the pool descriptor */ RTL::Atomic::Increment32((PLONG)&PoolDescriptor->RunningAllocations); /* Register the allocation in the tracking table */ RegisterAllocationTag(Tag, PoolEntry->BlockSize * MM_POOL_BLOCK_SIZE, PoolType); /* Perform a final structural validation of the pool block */ VerifyPoolBlocks(PoolEntry); /* Apply the requested identification tag */ PoolEntry->PoolTag = Tag; /* Supply the allocated address and return success */ *Memory = GetPoolFreeBlock(PoolEntry); return STATUS_SUCCESS; } /** * Computes a hash for a given virtual address to be used in the big allocation tracker. * * @param VirtualAddress * Supplies the base virtual address to be hashed. * * @return This routine returns the computed hash value. * * @since XT 1.0 */ XTINLINE ULONG MM::Allocator::ComputeHash(IN PVOID VirtualAddress) { ULONG Result; /* Transform the virtual address into a page frame number representation */ Result = (ULONG)((ULONG_PTR)VirtualAddress >> MM_PAGE_SHIFT); /* Fold the page number bits using XOR to distribute the entropy across the lower bits */ return (Result >> 24) ^ (Result >> 16) ^ (Result >> 8) ^ Result; } /** * Computes a hash for a given pool tag to be used in the allocation tracker. * * @param Tag * Supplies the 32-bit pool tag to be hashed. * * @param TableMask * Supplies the bitmask used to bound the resulting hash index to the table size. * * @return This routine returns the computed hash value. * * @since XT 1.0 */ XTINLINE ULONG MM::Allocator::ComputeHash(IN ULONG Tag, IN ULONG TableMask) { ULONG Result; /* Fold the bytes using arithmetic shifts and XORs */ Result = ((((((Tag & 0xFF) << 2) ^ ((Tag >> 8) & 0xFF)) << 2) ^ ((Tag >> 16) & 0xFF)) << 2) ^ ((Tag >> 24) & 0xFF); /* Multiply by the NT magic prime-like constant and shift down */ return ((40543 * Result) >> 2) & TableMask; } /** * Expands the big allocation tracking table to accommodate additional large allocations. * * @return This routine returns TRUE if the table was successfully expanded, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Allocator::ExpandBigAllocationsTable(VOID) { PPOOL_TRACKING_BIG_ALLOCATIONS NewTable, OldTable; SIZE_T AllocationBytes, OldSize, NewSize; ULONG Hash, HashMask, Index; PFN_NUMBER PagesFreed; XTSTATUS Status; BOOLEAN Abort; /* Initialize the abort flag and snapshot current table capacity */ Abort = FALSE; OldSize = BigAllocationsTrackingTableSize; /* Check if doubling the size would cause an integer overflow */ if(OldSize > ((~(SIZE_T)0) / 2)) { /* Abort expansion to prevent integer wrap-around */ return FALSE; } /* Calculate the target capacity by safely doubling table capacity */ NewSize = OldSize * 2; /* Ensure the new capacity does not result in fractional memory pages */ NewSize = ROUND_DOWN(NewSize, MM_PAGE_SIZE / sizeof(POOL_TRACKING_BIG_ALLOCATIONS)); /* Check if calculating the total byte size would cause an integer overflow */ if(NewSize > ((~(SIZE_T)0) / sizeof(POOL_TRACKING_BIG_ALLOCATIONS))) { /* Abort expansion to prevent allocating a truncated memory block */ return FALSE; } /* Compute the size required for the newly expanded tracking table */ AllocationBytes = NewSize * sizeof(POOL_TRACKING_BIG_ALLOCATIONS); /* Allocate the required memory */ Status = AllocatePages(NonPagedPool, AllocationBytes, (PVOID*)&NewTable); if(Status != STATUS_SUCCESS || !NewTable) { /* Memory allocation failed, abort the table expansion */ return FALSE; } /* Zero the newly allocated table */ RTL::Memory::ZeroMemory(NewTable, AllocationBytes); /* Iterate through the allocated memory block */ for(Index = 0; Index < NewSize; Index++) { /* Mark the tracking entry as free and available */ NewTable[Index].VirtualAddress = (PVOID)MM_POOL_BIG_ALLOCATIONS_ENTRY_FREE; } /* Start a guarded code block */ { /* Acquire the tracking table lock and raise runlevel to DISPATCH level */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::SpinLockGuard TrackingTableLock(&BigAllocationsTrackingTableLock); /* Verify if another thread has already expanded the table concurrently */ if(BigAllocationsTrackingTableSize >= NewSize) { /* Another thread has already expanded the table, discard changes */ Abort = TRUE; } else { /* Cache the legacy table pointer and calculate new hash mask */ HashMask = NewSize - 1; OldTable = BigAllocationsTrackingTable; /* Rehash and migrate all active entries from the old table */ for(Index = 0; Index < OldSize; Index++) { /* Bypass unallocated entries in the legacy table */ if((ULONG_PTR)OldTable[Index].VirtualAddress & MM_POOL_BIG_ALLOCATIONS_ENTRY_FREE) { /* Skip to the next entry */ continue; } /* Compute the updated hash index */ Hash = ComputeHash(OldTable[Index].VirtualAddress) & HashMask; /* Resolve hash collisions using linear probing */ while(!((ULONG_PTR)NewTable[Hash].VirtualAddress & MM_POOL_BIG_ALLOCATIONS_ENTRY_FREE)) { /* Advance the bucket index and check for table boundary overflow */ if(++Hash == NewSize) { /* Wrap the probing index back to the beginning */ Hash = 0; } } /* Migrate the active entry to its new hash bucket */ NewTable[Hash] = OldTable[Index]; } /* Activate the newly populated table globally */ BigAllocationsTrackingTable = NewTable; BigAllocationsTrackingTableHash = NewSize - 1; BigAllocationsTrackingTableSize = NewSize; } } /* Check if another thread has already expanded the table concurrently */ if(Abort) { /* Free memory allocated for the new table and return */ FreePages(NewTable); return TRUE; } /* Free memory allocated for the legacy table */ FreePages(OldTable, &PagesFreed); /* Update the pool tracking statistics */ UnregisterAllocationTag(SIGNATURE32('M', 'M', 'g', 'r'), PagesFreed << MM_PAGE_SHIFT, (MMPOOL_TYPE)0); RegisterAllocationTag(SIGNATURE32('M', 'M', 'g', 'r'), ROUND_UP(NewSize, MM_PAGE_SIZE), (MMPOOL_TYPE)0); /* Return success */ return TRUE; } /** * Frees a previously allocated block of pages from the non-paged pool. * * @param VirtualAddress * Supplies the base virtual address of the non-paged pool pages allocation to free. * * @param PagesFreed * Supplies a pointer to a variable that will receive the number of pages freed. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Allocator::FreeNonPagedPoolPages(IN PVOID VirtualAddress, OUT PPFN_NUMBER PagesFreed) { PMMFREE_POOL_ENTRY FreePage, NextPage, LastPage; PMMMEMORY_LAYOUT MemoryLayout; PFN_COUNT FreePages, Pages; PFN_NUMBER PageFrameNumber; PMMPFN Pfn, FirstPfn; PMMPTE PointerPte; ULONG Index; /* Retrieve memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Get the first PTE of the allocation */ PointerPte = MM::Paging::GetPteAddress(VirtualAddress); Pfn = MM::Pfn::GetPfnEntry(MM::Paging::GetPageFrameNumber(PointerPte)); /* Verify that the address is within the non-paged pool */ if((VirtualAddress < MemoryLayout->NonPagedPoolStart || VirtualAddress >= MemoryLayout->NonPagedPoolEnd) && (VirtualAddress < MemoryLayout->NonPagedExpansionPoolStart || VirtualAddress >= MemoryLayout->NonPagedExpansionPoolEnd)) { /* Address does not belong to the non-paged pool, raise kernel panic */ KE::Crash::Panic(0xC2, 0x43, (ULONG_PTR)VirtualAddress, 0, 0); } /* Basic sanity check to prevent double-frees or freeing unallocated memory */ if(Pfn->u3.e1.ReadInProgress == 0) { /* Address is not an allocation head, raise kernel panic */ KE::Crash::Panic(0xC2, 0x41, (ULONG_PTR)VirtualAddress, (ULONG_PTR)Pfn, 0); } /* Save the first PFN entry and initialize the allocation page counter */ FirstPfn = Pfn; Pages = 1; /* Seek to the end of the allocation */ while(Pfn->u3.e1.WriteInProgress == 0) { /* Get the next PTE and its PFN */ PointerPte = MM::Paging::GetNextPte(PointerPte); Pfn = MM::Pfn::GetPfnEntry(MM::Paging::GetPageFrameNumber(PointerPte)); /* Increment the page count */ Pages++; } /* Save the total free page count */ FreePages = Pages; /* Acquire the Non-Paged pool lock and raise runlevel to DISPATCH level */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::QueuedSpinLockGuard NonPagedPoolSpinLock(NonPagedPoolLock); /* Denote allocation boundaries */ FirstPfn->u3.e1.ReadInProgress = 0; Pfn->u3.e1.WriteInProgress = 0; /* Check if the address belongs to the non-paged expansion pool */ if(VirtualAddress >= MemoryLayout->NonPagedExpansionPoolStart) { /* Check if the allocation spans more than 3 pages and should be reclaimed */ if(Pages > 3) { /* Get the first PTE of the allocation and iterate over all pages */ PointerPte = MM::Paging::GetPteAddress(VirtualAddress); for(Index = 0; Index < Pages; Index++) { /* Get the page frame number from the PTE */ PageFrameNumber = MM::Paging::GetPageFrameNumber(PointerPte); Pfn = MM::Pfn::GetPfnEntry(PageFrameNumber); /* Clear PFN shared count and mark the PFN as ready for removal */ Pfn->u2.ShareCount = 0; Pfn->PteAddress = (PMMPTE)((ULONG_PTR)Pfn->PteAddress | 0x1); /* Decrement the reference count of the page table */ MM::Pfn::DecrementReferenceCount(Pfn, PageFrameNumber, FALSE); /* Invalidate the PTE */ MM::Paging::ClearPte(PointerPte); /* Get the next PTE */ PointerPte = MM::Paging::GetNextPte(PointerPte); } /* Release reserved system PTEs back to the pool */ MM::Pte::ReleaseSystemPtes(MM::Paging::GetPteAddress(VirtualAddress), Pages, NonPagedPoolExpansion); /* Check if a page count was requested */ if(PagesFreed != NULLPTR) { /* Return the number of pages freed */ *PagesFreed = FreePages; } /* Return success */ return STATUS_SUCCESS; } } /* Get the next PTE */ PointerPte = MM::Paging::GetNextPte(PointerPte); /* Check if the end of the initial nonpaged pool has been reached */ if(Pfn - MemoryLayout->PfnDatabase == NonPagedPoolFrameEnd) { /* Ignore the last page of the initial nonpaged pool */ Pfn = NULLPTR; } else { /* Check if the PTE is valid */ if(MM::Paging::PteValid(PointerPte)) { /* Get the PFN entry for the page laying in either the expansion or initial non-paged pool */ Pfn = MM::Pfn::GetPfnEntry(MM::Paging::GetPageFrameNumber(PointerPte)); } else { /* Ignore the last page of the non-paged expansion pool */ Pfn = NULLPTR; } } /* Check if the adjacent physical page following the allocation is free */ if((Pfn) && (Pfn->u3.e1.ReadInProgress == 0)) { /* Calculate the virtual address of the adjacent forward free pool entry */ FreePage = (PMMFREE_POOL_ENTRY)((ULONG_PTR)VirtualAddress + (Pages << MM_PAGE_SHIFT)); /* Absorb the adjacent free block's pages into the current free page count */ FreePages += FreePage->Size; /* Unlink the adjacent free block from its current segregated free list */ RTL::LinkedList::RemoveEntryList(&FreePage->List); } /* Get the free pool entry structure from the list entry */ FreePage = (PMMFREE_POOL_ENTRY)VirtualAddress; /* Check if the beginning of the initial nonpaged pool has been reached */ if(FirstPfn - MemoryLayout->PfnDatabase == NonPagedPoolFrameStart) { /* Ignore the first page of the initial nonpaged pool */ Pfn = NULLPTR; } else { /* Calculate the PTE address for the page immediately preceding the allocation */ PointerPte = MM::Paging::AdvancePte(PointerPte, -Pages - 1); /* Check if the PTE is valid */ if(MM::Paging::PteValid(PointerPte)) { /* Get the PFN entry for the page laying in either the expansion or initial nonpaged pool */ Pfn = MM::Pfn::GetPfnEntry(MM::Paging::GetPageFrameNumber(PointerPte)); } else { /* Ignore the first page of the expansion nonpaged pool */ Pfn = NULLPTR; } } /* Check if the adjacent physical page preceding the allocation is free */ if((Pfn) && (Pfn->u3.e1.WriteInProgress == 0)) { /* Retrieve the owner header of the preceding free block for backward coalescing */ FreePage = (PMMFREE_POOL_ENTRY)((ULONG_PTR)VirtualAddress - MM_PAGE_SIZE); FreePage = FreePage->Owner; /* Check if the allocation is small enough */ if(FreePage->Size < MM_MAX_FREE_PAGE_LIST_HEADS) { /* Remove the entry from the list */ RTL::LinkedList::RemoveEntryList(&FreePage->List); /* Adjust the size of the free block to account for the allocated pages */ FreePage->Size += FreePages; /* Calculate the new list index */ Index = MIN(FreePage->Size, MM_MAX_FREE_PAGE_LIST_HEADS) - 1; /* Insert the entry into the head of the list */ RTL::LinkedList::InsertHeadList(&NonPagedPoolFreeList[Index], &FreePage->List); } else { /* Adjust the size of the free block to account for the allocated pages */ FreePage->Size += FreePages; } } /* Check if backward coalescing failed, requiring the freed block to become a new list head */ if(FreePage == VirtualAddress) { /* Adjust the size of the free block to account for the allocated pages */ FreePage->Size = FreePages; /* Calculate the new list index */ Index = MIN(FreePage->Size, MM_MAX_FREE_PAGE_LIST_HEADS) - 1; /* Insert the entry into the head of the list */ RTL::LinkedList::InsertHeadList(&NonPagedPoolFreeList[Index], &FreePage->List); } /* Calculate the start and end boundaries for updating the owner pointers */ NextPage = (PMMFREE_POOL_ENTRY)VirtualAddress; LastPage = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextPage + (FreePages << MM_PAGE_SHIFT)); /* Iterate through all freed and coalesced pages to update their owner reference */ while(NextPage != LastPage) { /* Link the page to the owner */ NextPage->Owner = FreePage; NextPage = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextPage + MM_PAGE_SIZE); } /* Check if a page count was requested */ if(PagesFreed != NULLPTR) { /* Return the number of pages freed */ *PagesFreed = FreePages; } /* Return success */ return STATUS_SUCCESS; } /** * Frees a previously allocated block of pages from the paged pool. * * @param VirtualAddress * Supplies the base virtual address of the paged pool pages allocation to free. * * @param PagesFreed * Supplies a pointer to a variable that will receive the number of pages freed. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Allocator::FreePagedPoolPages(IN PVOID VirtualAddress, OUT PPFN_NUMBER PagesFreed) { UNIMPLEMENTED; /* Return not implemented status code */ return STATUS_NOT_IMPLEMENTED; } /** * Frees a previously allocated block of pages. * * @param VirtualAddress * Supplies the base virtual address of the pages allocation to free. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Allocator::FreePages(IN PVOID VirtualAddress) { return FreePages(VirtualAddress, NULLPTR); } /** * Frees a previously allocated block of pages. * * @param VirtualAddress * Supplies the base virtual address of the pages allocation to free. * * @param PagesFreed * Supplies a pointer to a variable that will receive the number of pages freed. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Allocator::FreePages(IN PVOID VirtualAddress, OUT PPFN_NUMBER PagesFreed) { PMMMEMORY_LAYOUT MemoryLayout; /* Retrieve memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Check if the address is in the paged pool */ if(VirtualAddress >= MemoryLayout->PagedPoolStart && VirtualAddress < MemoryLayout->PagedPoolEnd) { /* Free pages from the paged pool */ return FreePagedPoolPages(VirtualAddress, PagesFreed); } else { /* Free pages from the non-paged pool */ return FreeNonPagedPoolPages(VirtualAddress, PagesFreed); } } /** * Frees a previously allocated memory pool. * * @param VirtualAddress * Supplies the base virtual address of the pool allocation to free. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Allocator::FreePool(IN PVOID VirtualAddress) { /* Free pool */ return FreePool(VirtualAddress, SIGNATURE32('N', 'o', 'n', 'e')); } /** * Frees a previously allocated memory pool. * * @param VirtualAddress * Supplies the base virtual address of the pool allocation to free. * * @param Tag * Specifies the allocation identifying tag. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Allocator::FreePool(IN PVOID VirtualAddress, IN ULONG Tag) { PPOOL_HEADER PoolEntry, NextPoolEntry; PFN_NUMBER PageCount, RealPageCount; PPOOL_DESCRIPTOR PoolDescriptor; MMPOOL_TYPE PoolType; USHORT BlockSize; BOOLEAN Combined; XTSTATUS Status; /* Determine if the allocation is page-aligned */ if(PAGE_ALIGN(VirtualAddress) == VirtualAddress) { /* Determine and the memory pool type from the VA mapping */ PoolType = DeterminePoolType(VirtualAddress); /* Verify run level for the specified pool */ VerifyRunLevel(PoolType, 0, VirtualAddress); /* Retrieve original metadata while removing the allocation from the tracking table */ Tag = UnregisterBigAllocationTag(VirtualAddress, &PageCount, PoolType); if(Tag & MM_POOL_PROTECTED) { /* Strip the protected pool bit */ Tag &= ~MM_POOL_PROTECTED; } else if(!Tag) { /* Fallback to a default tag */ Tag = SIGNATURE32('B', 'i', 'g', 'A'); PageCount = 1; } /* Remove the allocation from the tracking table */ UnregisterAllocationTag(Tag, PageCount << MM_PAGE_SHIFT, PoolType); /* Retrieve the specific pool descriptor based on the masked pool type */ PoolDescriptor = PoolVector[PoolType]; /* Update the pool descriptor statistical counters */ RTL::Atomic::Increment32((PLONG)&PoolDescriptor->RunningFrees); RTL::Atomic::ExchangeAdd64((PLONG_PTR)&PoolDescriptor->TotalBytes, -(LONG_PTR)(PageCount << MM_PAGE_SHIFT)); /* Release the underlying physical pages */ Status = FreePages(VirtualAddress, &RealPageCount); if(Status == STATUS_SUCCESS) { /* Adjust the big allocation counter */ RTL::Atomic::ExchangeAdd32((PLONG)&PoolDescriptor->TotalBigAllocations, -(LONG)RealPageCount); } /* Return status code */ return Status; } /* Resolve the pool header */ PoolEntry = (PPOOL_HEADER)VirtualAddress; PoolEntry--; /* Extract the structural block size from the pool header */ BlockSize = PoolEntry->BlockSize; /* Determine the underlying pool type and resolve its corresponding pool descriptor */ PoolType = (MMPOOL_TYPE)((PoolEntry->PoolType - 1) & MM_POOL_TYPE_MASK); PoolDescriptor = PoolVector[PoolType]; /* Verify run level for the specified pool */ VerifyRunLevel(PoolType, 0, VirtualAddress); /* Extract the allocation identifying tag and initialize the consolidation flag */ Tag = PoolEntry->PoolTag; Combined = FALSE; /* Check if the allocation tag carries the protected pool modifier */ if(Tag & MM_POOL_PROTECTED) { /* Strip the protected pool bit */ Tag &= ~MM_POOL_PROTECTED; } /* Remove the allocation from the tracking table */ UnregisterAllocationTag(Tag, BlockSize * MM_POOL_BLOCK_SIZE, (MMPOOL_TYPE)(PoolEntry->PoolType - 1)); /* Locate the adjacent forward pool block */ NextPoolEntry = GetPoolBlock(PoolEntry, BlockSize); /* Update the pool descriptor statistical counters */ RTL::Atomic::Increment32((PLONG)&PoolDescriptor->RunningFrees); RTL::Atomic::ExchangeAdd64((PLONG_PTR)&PoolDescriptor->TotalBytes, (LONG_PTR)(-BlockSize * MM_POOL_BLOCK_SIZE)); /* Acquire the pool lock */ PoolLockGuard PoolLock((MMPOOL_TYPE)(PoolDescriptor->PoolType & MM_POOL_TYPE_MASK)); /* Validate the structural integrity of the base block */ VerifyPoolBlocks(PoolEntry); /* Ensure the adjacent forward block does not cross a page boundary */ if(PAGE_ALIGN(NextPoolEntry) != NextPoolEntry) { /* Check if the adjacent forward block is currently marked as free */ if(NextPoolEntry->PoolType == 0) { /* Flag the deallocation as having triggered a forward block merge */ Combined = TRUE; /* Check if the forward block is large enough */ if(NextPoolEntry->BlockSize != 1) { /* Validate the list links */ VerifyPoolLinks(GetPoolFreeBlock(NextPoolEntry)); /* Unlink the forward block from its respective free list */ RemovePoolEntryList(GetPoolFreeBlock(NextPoolEntry)); /* Re-validate the surrounding list links */ VerifyPoolLinks(DecodePoolLink((GetPoolFreeBlock(NextPoolEntry))->Flink)); VerifyPoolLinks(DecodePoolLink((GetPoolFreeBlock(NextPoolEntry))->Blink)); } /* Expand the size of the current block to include the forward free block */ PoolEntry->BlockSize += NextPoolEntry->BlockSize; } } /* Check if a valid adjacent backward block exists */ if(PoolEntry->PreviousSize) { /* Resolve the adjacent backward block and check if it is free */ NextPoolEntry = GetPoolPreviousBlock(PoolEntry); if(NextPoolEntry->PoolType == 0) { /* Flag the deallocation as having triggered a backward block merge */ Combined = TRUE; /* Check if the backward free block contains embedded list links */ if(NextPoolEntry->BlockSize != 1) { /* Validate the backward block list links */ VerifyPoolLinks(GetPoolFreeBlock(NextPoolEntry)); /* Extract the backward block from the free list */ RemovePoolEntryList(GetPoolFreeBlock(NextPoolEntry)); /* Re-validate the adjacent free list */ VerifyPoolLinks(DecodePoolLink((GetPoolFreeBlock(NextPoolEntry))->Flink)); VerifyPoolLinks(DecodePoolLink((GetPoolFreeBlock(NextPoolEntry))->Blink)); } /* Expand the backward block to include the freed base block */ NextPoolEntry->BlockSize += PoolEntry->BlockSize; /* Shift the base entry pointer */ PoolEntry = NextPoolEntry; } } /* Check whether the consolidated block spans an entire page */ if((PAGE_ALIGN(PoolEntry) == PoolEntry) && (PAGE_ALIGN(GetPoolNextBlock(PoolEntry)) == GetPoolNextBlock(PoolEntry))) { /* Release the pool lock */ PoolLock.Release(); /* Decrement the total page count and return the entire page back */ RTL::Atomic::ExchangeAdd32((PLONG)&PoolDescriptor->TotalPages, -1); return FreePages(PoolEntry); } /* Finalize the consolidated block size and mark the primary header as free */ BlockSize = PoolEntry->BlockSize; PoolEntry->PoolType = 0; /* Check if any coalescing occurred */ if(Combined) { /* Resolve the new adjacent forward block and verify it resides on the same page */ NextPoolEntry = GetPoolNextBlock(PoolEntry); if(PAGE_ALIGN(NextPoolEntry) != NextPoolEntry) { /* Adjust the backward reference of the forward block */ NextPoolEntry->PreviousSize = BlockSize; } } /* Insert the freed and consolidated block into the pool free list */ InsertPoolHeadList(&PoolDescriptor->ListHeads[BlockSize - 1], GetPoolFreeBlock(PoolEntry)); /* Perform a final linkvalidation and return success */ VerifyPoolLinks(GetPoolFreeBlock(PoolEntry)); return STATUS_SUCCESS; } /** * Initializes the allocations tracking table during early system boot. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Allocator::InitializeAllocationsTracking(VOID) { SIZE_T TableSize; ULONG Index; XTSTATUS Status; PMMMEMORY_LAYOUT MemoryLayout; /* Not fully implemented yet, HIVE support needed */ UNIMPLEMENTED; /* Retrieve memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* TODO: Retrieve tracking table size from the HIVE */ AllocationsTrackingTableSize = 0; /* Calculate the target table size */ TableSize = MIN(AllocationsTrackingTableSize, (MemoryLayout->NonPagedPoolSize * MM_PAGE_SIZE) >> 8); /* Perform a bit-scan to determine the highest set bit */ for(Index = 0; Index < 32; Index++) { /* Check if the lowest bit is currently set */ if(TableSize & 1) { /* Verify if this is the only remaining set bit */ if(!(TableSize & ~1)) { /* Exit the loop as the highest bit has been found */ break; } } /* Shift the size down by one bit to evaluate higher bits */ TableSize >>= 1; } /* Check if the bit-scan completed without finding any set bits */ if(Index == 32) { /* Apply the default size of 1024 entries */ AllocationsTrackingTableSize = 1024; } else { /* Calculate the aligned power of two size, enforcing a minimum of 64 entries */ AllocationsTrackingTableSize = MAX(1 << Index, 64); } /* Iteratively attempt to allocate the tracking table */ while(TRUE) { /* Prevent integer overflow when calculating the required byte size for the table */ if(AllocationsTrackingTableSize + 1 > (MAXULONG_PTR / sizeof(POOL_TRACKING_TABLE))) { /* Halve the requested entry count and restart the evaluation */ AllocationsTrackingTableSize >>= 1; continue; } /* Attempt to allocate physical memory for the table */ Status = MM::Allocator::AllocatePages(NonPagedPool, (AllocationsTrackingTableSize + 1) * sizeof(POOL_TRACKING_TABLE), (PVOID *)&AllocationsTrackingTable); /* Check if the allocation succeeded */ if(Status != STATUS_SUCCESS || !AllocationsTrackingTable) { /* Check if the allocation failed duefor a single entry */ if(AllocationsTrackingTableSize == 1) { /* Failed to initialize the pool tracker, raise kernel panic */ KE::Crash::Panic(0x41, TableSize, (ULONG_PTR)~0, (ULONG_PTR)~0, (ULONG_PTR)~0); } /* Halve the requested entry count */ AllocationsTrackingTableSize >>= 1; } else { /* Allocation succeeded */ break; } } /* Increment the table size to account for the overflow bucket entry */ AllocationsTrackingTableSize++; /* Zero the entire memory used by the table */ RtlZeroMemory(AllocationsTrackingTable, AllocationsTrackingTableSize * sizeof(POOL_TRACKING_TABLE)); /* Assign the global tracking table as the local table for the bootstrap processor */ TagTables[0] = AllocationsTrackingTable; /* Calculate and store the hash mask */ AllocationsTrackingTableMask = AllocationsTrackingTableSize - 2; /* Initialize the spinlock used to synchronize concurrent modifications to the tracking table */ KE::SpinLock::InitializeSpinLock(&AllocationsTrackingTableLock); } /** * Initializes the big allocations tracking table during early system boot. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Allocator::InitializeBigAllocationsTracking(VOID) { SIZE_T TableSize; ULONG Index; XTSTATUS Status; PMMMEMORY_LAYOUT MemoryLayout; /* Not fully implemented yet, HIVE support needed */ UNIMPLEMENTED; /* Retrieve memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* TODO: Retrieve initial big allocation table size from the HIVE */ BigAllocationsTrackingTableSize = 0; /* Calculate the target table size */ TableSize = MIN(BigAllocationsTrackingTableSize, (MemoryLayout->NonPagedPoolSize * MM_PAGE_SIZE) >> 12); /* Perform a bit-scan to determine the highest set bit */ for(Index = 0; Index < 32; Index++) { /* Check if the lowest bit is currently set */ if(TableSize & 1) { /* Verify if this is the only remaining set bit */ if(!(TableSize & ~1)) { /* Exit the loop as the highest bit has been found */ break; } } /* Shift the size down by one bit to evaluate higher bits */ TableSize >>= 1; } /* Check if the bit-scan completed without finding any set bits */ if(Index == 32) { /* Apply the default size of 4096 entries */ BigAllocationsTrackingTableSize = 4096; } else { /* Calculate the aligned power of two size, enforcing a minimum of 64 entries */ BigAllocationsTrackingTableSize = MAX(1 << Index, 64); } /* Iteratively attempt to allocate the tracking table */ while(TRUE) { /* Prevent integer overflow when calculating the required byte size for the table */ if((BigAllocationsTrackingTableSize + 1) > (MAXULONG_PTR / sizeof(POOL_TRACKING_BIG_ALLOCATIONS))) { /* Halve the requested entry count and restart the evaluation */ BigAllocationsTrackingTableSize >>= 1; continue; } /* Attempt to allocate physical memory for the table */ Status = AllocatePages(NonPagedPool, BigAllocationsTrackingTableSize * sizeof(POOL_TRACKING_BIG_ALLOCATIONS), (PVOID*)&BigAllocationsTrackingTable); /* Check if the allocation succeeded */ if(Status != STATUS_SUCCESS || !BigAllocationsTrackingTable) { /* Check if the allocation failed duefor a single entry */ if(BigAllocationsTrackingTableSize == 1) { /* Failed to initialize the pool tracker, raise kernel panic */ KE::Crash::Panic(0x41, TableSize, (ULONG_PTR)~0, (ULONG_PTR)~0, (ULONG_PTR)~0); } /* Halve the requested entry count */ BigAllocationsTrackingTableSize >>= 1; } else { /* Allocation succeeded */ break; } } /* Zero the entire memory used by the table */ RtlZeroMemory(BigAllocationsTrackingTable, BigAllocationsTrackingTableSize * sizeof(POOL_TRACKING_BIG_ALLOCATIONS)); /* Iterate through the newly allocated table */ for(Index = 0; Index < BigAllocationsTrackingTableSize; Index++) { /* Mark the individual pool tracker entry as free and available */ BigAllocationsTrackingTable[Index].VirtualAddress = (PVOID)MM_POOL_BIG_ALLOCATIONS_ENTRY_FREE; } /* Calculate and store the hash mask */ BigAllocationsTrackingTableHash = BigAllocationsTrackingTableSize - 1; /* Initialize the spinlock used to synchronize concurrent modifications to the tracking table */ KE::SpinLock::InitializeSpinLock(&BigAllocationsTrackingTableLock); /* Register the allocation in the tracking table */ RegisterAllocationTag(SIGNATURE32('M', 'M', 'g', 'r'), SIZE_TO_PAGES(BigAllocationsTrackingTableSize * sizeof(POOL_TRACKING_BIG_ALLOCATIONS)), NonPagedPool); } /** * Registers a pool memory allocation in the tracking table. * * @param Tag * Supplies the tag used to identify the allocation. * * @param Bytes * Supplies the size of the allocation. * * @param PoolType * Specifies the type of pool from which the memory was allocated. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Allocator::RegisterAllocationTag(IN ULONG Tag, IN SIZE_T Bytes, IN MMPOOL_TYPE PoolType) { PPOOL_TRACKING_TABLE CpuTable, TableEntry; ULONG Hash, Index, Processor; /* Retrieve the local tracking table for the current processor */ Processor = KE::Processor::GetCurrentProcessorNumber(); CpuTable = TagTables[Processor]; /* Strip the protected pool bit */ Tag &= ~MM_POOL_PROTECTED; /* Compute the initial hash index */ Hash = ComputeHash(Tag, AllocationsTrackingTableMask); Index = Hash; /* Probe the tracking table until a match or an empty slot is found */ do { /* Fetch the tracker entry from the CPU table */ TableEntry = &CpuTable[Hash]; /* Check if the current entry tracks the requested pool tag */ if(TableEntry->Tag == Tag) { /* Update the appropriate statistics based on the pool type */ if((PoolType & MM_POOL_TYPE_MASK) == NonPagedPool) { /* Update the non-paged allocation statistics */ RTL::Atomic::Increment32(&TableEntry->NonPagedAllocations); RTL::Atomic::ExchangeAdd64((PLONG_PTR)&TableEntry->NonPagedBytes, Bytes); } else { /* Update the paged allocation statistics */ RTL::Atomic::Increment32(&TableEntry->PagedAllocations); RTL::Atomic::ExchangeAdd64((PLONG_PTR)&TableEntry->PagedBytes, Bytes); } /* The allocation has been successfully tracked, return */ return; } /* Check if the CPU table is entirely empty */ if(TableEntry->Tag == 0) { /* Check if another processor has claimed this slot in the global table */ if(AllocationsTrackingTable[Hash].Tag != 0) { /* Synchronize the local table with the global table */ TableEntry->Tag = AllocationsTrackingTable[Hash].Tag; /* Restart the loop to evaluation */ continue; } /* Check if this is not the designated overflow bucket */ if(Hash != (AllocationsTrackingTableSize - 1)) { /* Start a guarded code block */ { /* Acquire the tracking table lock */ KE::SpinLockGuard TrackingTableLock(&AllocationsTrackingTableLock); /* Perform a double-checked lock */ if(AllocationsTrackingTable[Hash].Tag == 0) { /* Claim the slot in both, local and global tracking tables */ AllocationsTrackingTable[Hash].Tag = Tag; TableEntry->Tag = Tag; } } /* Restart the loop */ continue; } } /* Advance to the next index as hash collision occurred */ Hash = (Hash + 1) & AllocationsTrackingTableMask; } while(Hash != Index); /* Fallback to the expansion path */ RegisterAllocationTagExpansion(Tag, Bytes, PoolType); } /** * Registers a pool memory allocation in the tracking expansion table. * * @param Tag * Supplies the tag used to identify the allocation. * * @param Bytes * Supplies the size of the allocation. * * @param PoolType * Specifies the type of pool from which the memory was allocated. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Allocator::RegisterAllocationTagExpansion(IN ULONG Tag, IN SIZE_T Bytes, IN MMPOOL_TYPE PoolType) { PPOOL_TRACKING_TABLE NewTrackingTable, OldTrackingTable; SIZE_T Footprint, NewSize, Size; BOOLEAN UseOverflowBucket; PFN_NUMBER FreedPages; XTSTATUS Status; ULONG Hash; /* Initialize local state */ NewTrackingTable = NULLPTR; OldTrackingTable = NULLPTR; UseOverflowBucket = FALSE; /* Start a guarded code block */ { /* Acquire the tracking table lock */ KE::SpinLockGuard TrackingTableLock(&AllocationsTrackingTableLock); /* Scan the expansion table to locate the requested tag */ for(Hash = 0; Hash < AllocationsTrackingExpansionTableSize; Hash++) { /* Check if the current entry already tracks the requested pool tag */ if(AllocationsTrackingExpansionTable[Hash].Tag == Tag) { /* Target entry found, break out */ break; } /* Check if an unassigned slot has been reached */ if(AllocationsTrackingExpansionTable[Hash].Tag == 0) { /* Claim the empty slot for the new pool tag and stop searching */ AllocationsTrackingExpansionTable[Hash].Tag = Tag; break; } } /* Check if the tag was successfully located or a new slot was successfully claimed */ if(Hash != AllocationsTrackingExpansionTableSize) { /* Update the appropriate statistics based on the pool type */ if((PoolType & MM_POOL_TYPE_MASK) == NonPagedPool) { /* Update the non-paged allocation statistics */ AllocationsTrackingExpansionTable[Hash].NonPagedAllocations++; AllocationsTrackingExpansionTable[Hash].NonPagedBytes += Bytes; } else { /* Update the paged allocation statistics */ AllocationsTrackingExpansionTable[Hash].PagedAllocations++; AllocationsTrackingExpansionTable[Hash].PagedBytes += Bytes; } /* Nothing more to do */ return; } /* Check if the global overflow bucket has been activated */ if(AllocationsTrackingTable[AllocationsTrackingTableSize - 1].Tag != 0) { /* Use the overflow bucket */ UseOverflowBucket = TRUE; } else { /* Calculate the exact bytes of the expansion table */ Size = AllocationsTrackingExpansionTableSize * sizeof(POOL_TRACKING_TABLE); /* Determine the required physical memory */ Footprint = ROUND_UP(Size, MM_PAGE_SIZE) + MM_PAGE_SIZE; /* Calculate the usable byte size */ NewSize = ((Footprint / sizeof(POOL_TRACKING_TABLE)) * sizeof(POOL_TRACKING_TABLE)); /* Allocate memory for the expanded tracking table */ Status = AllocatePages(NonPagedPool, NewSize, (PVOID *)&NewTrackingTable); if(Status != STATUS_SUCCESS || !NewTrackingTable) { /* Activate the global overflow bucket */ AllocationsTrackingTable[AllocationsTrackingTableSize - 1].Tag = SIGNATURE32('O', 'v', 'f', 'l'); UseOverflowBucket = TRUE; } else { /* Check if a previous expansion table exists */ if(AllocationsTrackingExpansionTable != NULLPTR) { /* Migrate the existing tracking entries into the new expansion table */ RtlCopyMemory(NewTrackingTable, AllocationsTrackingExpansionTable, Size); } /* Zero out the added usable space */ RtlZeroMemory((PVOID)(NewTrackingTable + AllocationsTrackingExpansionTableSize), NewSize - Size); /* Swap the active expansion table pointers and update the entry count */ OldTrackingTable = AllocationsTrackingExpansionTable; AllocationsTrackingExpansionTable = NewTrackingTable; AllocationsTrackingExpansionTableSize = Footprint / sizeof(POOL_TRACKING_TABLE);; /* Register the new allocation tag */ RegisterAllocationTag(SIGNATURE32('M', 'M', 'g', 'r'), Footprint, NonPagedPool); } } } /* Handle the fallback scenario */ if(UseOverflowBucket) { /* Target the overflow bucket at the end of the tracking table */ Hash = (ULONG)AllocationsTrackingTableSize - 1; /* Update the appropriate statistics based on the pool type */ if((PoolType & MM_POOL_TYPE_MASK) == NonPagedPool) { /* Update the non-paged allocation statistics */ RTL::Atomic::Increment32((PLONG)&AllocationsTrackingTable[Hash].NonPagedAllocations); RTL::Atomic::ExchangeAdd64((PLONG_PTR)&AllocationsTrackingTable[Hash].NonPagedBytes, Bytes); } else { /* Update the paged allocation statistics */ RTL::Atomic::Increment32((PLONG)&AllocationsTrackingTable[Hash].PagedAllocations); RTL::Atomic::ExchangeAdd64((PLONG_PTR)&AllocationsTrackingTable[Hash].PagedBytes, Bytes); } /* Nothing more to do */ return; } /* Check if an older expansion table needs to be freed */ if(OldTrackingTable != NULLPTR) { /* Free the old tracking table and unregister the allocation tag */ FreePages(OldTrackingTable, &FreedPages); UnregisterAllocationTag(SIGNATURE32('M', 'M', 'g', 'r'), (SIZE_T)FreedPages * MM_PAGE_SIZE, NonPagedPool); } /* Register the caller's original allocation */ RegisterAllocationTagExpansion(Tag, Bytes, PoolType); } /** * Registers a big allocation within the tracking table. * * @param VirtualAddress * Supplies the virtual address of the big allocation. * * @param Tag * Supplies the tag used to identify the allocation. * * @param Pages * Supplies the number of physical pages backing the allocation. * * @param PoolType * Specifies the type of pool from which the memory was allocated. * * @return This routine returns TRUE on successful insertion, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Allocator::RegisterBigAllocationTag(IN PVOID VirtualAddress, IN ULONG Tag, IN ULONG Pages, IN MMPOOL_TYPE PoolType) { PPOOL_TRACKING_BIG_ALLOCATIONS Entry; BOOLEAN Inserted, RequiresExpansion; ULONG Hash, StartHash; /* Wrap the insertion logic in a retry loop */ while(TRUE) { /* Initialize local variables */ Inserted = FALSE; RequiresExpansion = FALSE; /* Calculate the initial hash bucket index */ Hash = ComputeHash(VirtualAddress); /* Start a guarded code block */ { /* Acquire the tracking table lock and raise runlevel to DISPATCH level */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::SpinLockGuard TrackingTableLock(&BigAllocationsTrackingTableLock); /* Retrieve the tracker entry */ Hash &= BigAllocationsTrackingTableHash; StartHash = Hash; /* Traverse the hash table */ do { /* Retrieve the tracker entry */ Entry = &BigAllocationsTrackingTable[Hash]; /* Check if the current bucket is marked as free */ if((ULONG_PTR)Entry->VirtualAddress & MM_POOL_BIG_ALLOCATIONS_ENTRY_FREE) { /* Populate the available bucket with the allocation metadata */ Entry->NumberOfPages = Pages; Entry->Tag = Tag; Entry->VirtualAddress = VirtualAddress; /* Increment the global usage counter */ BigAllocationsInUse++; /* Determine if the table capacity has reached the critical 75% threshold */ if(BigAllocationsInUse > (BigAllocationsTrackingTableSize * 3 / 4)) { /* Flag the table for expansion */ RequiresExpansion = TRUE; } /* Mark insertion as successful and break out of the probing loop */ Inserted = TRUE; break; } /* Advance to the next bucket */ if(++Hash >= BigAllocationsTrackingTableSize) { /* Wrap the index back to the beginning of the table */ Hash = 0; } /* If the traversal has wrapped entirely back to the starting index, the table is saturated */ if(Hash == StartHash) { /* Break out of the probing loop */ break; } } while(Hash != StartHash); } /* Check if the insertion succeeded */ if(Inserted) { /* Check if a table expansion is required */ if(RequiresExpansion) { /* Trigger a table expansion asynchronously */ ExpandBigAllocationsTable(); } /* Return success */ return TRUE; } /* The table is completely saturated, attempt to expand the table */ if(ExpandBigAllocationsTable()) { /* The table was successfully expanded, retry the insertion */ continue; } /* Table expansion failed, break out of the retry loop */ break; } /* Return failure */ return FALSE; } /** * Unregisters a pool memory allocation in the tracking table. * * @param Tag * Supplies the tag used to identify the allocation. * * @param Bytes * Supplies the size of the allocation. * * @param PoolType * Specifies the type of pool from which the memory was allocated. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Allocator::UnregisterAllocationTag(IN ULONG Tag, IN SIZE_T Bytes, IN MMPOOL_TYPE PoolType) { ULONG Hash, Index; PPOOL_TRACKING_TABLE CpuTable; PPOOL_TRACKING_TABLE TableEntry; ULONG Processor; /* Retrieve the local tracking table for the current processor */ Processor = KE::Processor::GetCurrentProcessorNumber(); CpuTable = TagTables[Processor]; /* Strip the protected pool bit */ Tag &= ~MM_POOL_PROTECTED; /* Compute the initial hash index */ Hash = ComputeHash(Tag, AllocationsTrackingTableMask); Index = Hash; /* Probe the tracking table until a match or an empty slot is found */ do { /* Fetch the tracker entry from the CPU table */ TableEntry = &CpuTable[Hash]; /* Check if the current entry tracks the requested pool tag */ if(TableEntry->Tag == Tag) { /* Update the appropriate statistics based on the pool type */ if((PoolType & MM_POOL_TYPE_MASK) == NonPagedPool) { /* Update the non-paged allocation statistics */ RTL::Atomic::Increment32(&TableEntry->NonPagedFrees); RTL::Atomic::ExchangeAdd64((PLONG_PTR)&TableEntry->NonPagedBytes, 0 - Bytes); } else { /* Update the paged allocation statistics */ RTL::Atomic::Increment32(&TableEntry->PagedFrees); RTL::Atomic::ExchangeAdd64((PLONG_PTR)&TableEntry->PagedBytes, 0 - Bytes); } /* The allocation has been successfully tracked, return */ return; } /* Check if the CPU table is entirely empty */ if(TableEntry->Tag == 0) { /* Check if another processor has claimed this slot in the global table */ if(AllocationsTrackingTable[Hash].Tag != 0) { /* Synchronize the local table with the global table */ TableEntry->Tag = AllocationsTrackingTable[Hash].Tag; /* Restart the loop to evaluation */ continue; } } /* Advance to the next index as hash collision occurred */ Hash = (Hash + 1) & AllocationsTrackingTableMask; } while(Hash != Index); /* Fallback to the expansion path */ UnregisterAllocationTagExpansion(Tag, Bytes, PoolType); } /** * Unregisters a pool memory allocation in the tracking expansion table. * * @param Tag * Supplies the tag used to identify the allocation. * * @param Bytes * Supplies the size of the allocation. * * @param PoolType * Specifies the type of pool from which the memory was allocated. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Allocator::UnregisterAllocationTagExpansion(IN ULONG Tag, IN SIZE_T Bytes, IN MMPOOL_TYPE PoolType) { PPOOL_TRACKING_TABLE CpuTable; ULONG Hash; ULONG Processor; /* Start a guarded code block */ { /* Acquire the tracking table lock */ KE::SpinLockGuard TrackingTableLock(&AllocationsTrackingTableLock); /* Scan the expansion table */ for(Hash = 0; Hash < AllocationsTrackingExpansionTableSize; Hash++) { /* Check if the current entry matches the tag */ if(AllocationsTrackingExpansionTable[Hash].Tag == Tag) { /* Update the appropriate statistics based on the pool type */ if((PoolType & MM_POOL_TYPE_MASK) == NonPagedPool) { /* Update the non-paged allocation statistics */ AllocationsTrackingExpansionTable[Hash].NonPagedFrees++; AllocationsTrackingExpansionTable[Hash].NonPagedBytes -= Bytes; } else { /* Update the paged allocation statistics */ AllocationsTrackingExpansionTable[Hash].PagedFrees++; AllocationsTrackingExpansionTable[Hash].PagedBytes -= Bytes; } /* Nothing more to do */ return; } /* Check if an empty slot is encountered */ if(AllocationsTrackingExpansionTable[Hash].Tag == 0) { /* Stop scanning as all active tags are contiguous */ break; } } } /* Target the index of the overflow bucket */ Hash = (ULONG)AllocationsTrackingTableSize - 1; /* Retrieve the local tracking table for the current processor */ Processor = KE::Processor::GetCurrentProcessorNumber(); CpuTable = TagTables[Processor]; /* Update the appropriate statistics based on the pool type */ if((PoolType & MM_POOL_TYPE_MASK) == NonPagedPool) { /* Update the non-paged allocation statistics */ RTL::Atomic::Increment32((PLONG)&CpuTable[Hash].NonPagedFrees); RTL::Atomic::ExchangeAdd64((PLONG_PTR)&CpuTable[Hash].NonPagedBytes, 0 - Bytes); } else { /* Update the paged allocation statistics */ RTL::Atomic::Increment32((PLONG)&CpuTable[Hash].PagedFrees); RTL::Atomic::ExchangeAdd64((PLONG_PTR)&CpuTable[Hash].PagedBytes, 0 - Bytes); } } /** * Unregisters a big allocation from the tracking table and retrieves its metadata. * * @param VirtualAddress * Supplies the virtual address of the big allocation to be removed. * * @param Pages * Supplies the number of physical pages backing the allocation. * * @param PoolType * Specifies the pool type of the allocation. * * @return This routine returns the allocation pool tag if found, or a default signature otherwise. * * @since XT 1.0 */ XTAPI ULONG MM::Allocator::UnregisterBigAllocationTag(IN PVOID VirtualAddress, OUT PULONG_PTR Pages, IN MMPOOL_TYPE PoolType) { ULONG Hash, StartHash; ULONG PoolTag; BOOLEAN Found; PPOOL_TRACKING_BIG_ALLOCATIONS Entry; /* Initialize default state */ Found = FALSE; /* Calculate the initial hash bucket index */ Hash = ComputeHash(VirtualAddress); /* Start a guarded code block */ { /* Acquire the tracking table lock and raise runlevel to DISPATCH level */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::SpinLockGuard TrackingTableLock(&BigAllocationsTrackingTableLock); /* Mask the computed hash and record the starting bucket */ Hash &= BigAllocationsTrackingTableHash; StartHash = Hash; /* Traverse the hash table using linear probing to pinpoint the exact allocation address */ while(TRUE) { /* Retrieve the tracker entry */ Entry = &BigAllocationsTrackingTable[Hash]; /* Check if the bucket contains the target virtual address */ if(Entry->VirtualAddress == VirtualAddress) { /* Capture the allocation metadata */ *Pages = Entry->NumberOfPages; PoolTag = Entry->Tag; /* Invalidate the entry */ Entry->VirtualAddress = (PVOID)MM_POOL_BIG_ALLOCATIONS_ENTRY_FREE; /* Decrement the global usage counter */ BigAllocationsInUse--; /* Update the found flag and break out of the probing loop */ Found = TRUE; break; } /* Advance to the next bucket */ if(++Hash >= BigAllocationsTrackingTableSize) { /* Wrap the hash index back to zero */ Hash = 0; } /* Check if the traversal has wrapped entirely back to the starting index */ if(Hash == StartHash) { /* Abort the search */ break; } } } /* Evaluate the result of the table traversal */ if(Found) { /* Return the original tag captured from the tracker */ return PoolTag; } /* Return an empty page count and a fallback tag */ *Pages = 0; return SIGNATURE32('B', 'i', 'g', 'A'); } ================================================ FILE: xtoskrnl/mm/amd64/mmgr.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/amd64/mmgr.cc * DESCRIPTION: Memory Manager * DEVELOPERS: Aiken Harris */ #include /** * Calculates the maximum possible size of the non-paged pool. * * @param PoolSize * A pointer to a variable that will receive the number of pages available for the non-paged pool. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::ComputeMaximumNonPagedPoolSize(OUT PPFN_NUMBER PoolSize) { ULONG_PTR MaximumNonPagedPoolSize; /* Start with the 1MiB and add 400KiB for each MiB above 16MiB */ MaximumNonPagedPoolSize = 1048576 + (((MM::Pfn::GetNumberOfPhysicalPages() - 4096) / 256) * 409600); /* Check if non-paged pool does not exceed 128GiB */ if(MaximumNonPagedPoolSize > 137438953472) { /* Limit non-paged pool size to 128GiB */ MaximumNonPagedPoolSize = 137438953472; } /* Return non-paged pool size */ *PoolSize = SIZE_TO_PAGES(MaximumNonPagedPoolSize); } /** * Calculates the size of the non-paged pool. * * @param PoolSize * A pointer to a variable that will receive the number of pages available for the non-paged pool. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::ComputeNonPagedPoolSize(OUT PPFN_NUMBER PoolSize) { ULONG_PTR NonPagedPoolSize; /* Start with 1MiB and add 32KiB for each MiB above 16MiB */ NonPagedPoolSize = 1048576 + (((MM::Pfn::GetNumberOfPhysicalPages() - 4096) / 256) * 32768); /* Check if non-paged pool does not exceed 128GiB */ if(NonPagedPoolSize > 137438953472) { /* Limit non-paged pool size to 128GiB */ NonPagedPoolSize = 137438953472; } /* Return non-paged pool size in pages, aligned up to page size boundary */ *PoolSize = SIZE_TO_PAGES(ROUND_UP(NonPagedPoolSize, MM_PAGE_SIZE)); } /** * Calculates the size of the paged pool. * * @param PoolSize * A pointer to a variable that will receive the number of pages available for the paged pool. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::ComputePagedPoolSize(OUT PPFN_NUMBER PoolSize) { ULONGLONG PagedPoolSize, PteCount; ULONG PtesPerPage; /* Start with 4x maximum non-paged pool size and at least 48MiB */ ComputeMaximumNonPagedPoolSize(&PagedPoolSize); PagedPoolSize *= 4 * MM_PAGE_SIZE; /* Ensure that paged pool size is at least 48MiB */ if(PagedPoolSize < 50331648) { /* Increase paged pool size to at least 48MiB */ PagedPoolSize = 50331648; } /* Check if paged pool does not overlap non-paged pool */ if(PagedPoolSize > (ULONGLONG)MemoryLayout.NonPagedSystemPoolStart - (ULONGLONG)MemoryLayout.PagedPoolStart) { /* Limit paged pool size to maximum possible */ PagedPoolSize = (ULONGLONG)MemoryLayout.NonPagedSystemPoolStart - (ULONGLONG)MemoryLayout.PagedPoolStart; } /* Check if paged pool does not exceed 128GiB */ if(PagedPoolSize > 137438953472) { /* Limit paged pool size to 128GiB */ PagedPoolSize = 137438953472; } /* Get the number of PTEs per page and calculate size of paged pool */ PtesPerPage = MM::Pte::GetPtesPerPage(); PteCount = ((SIZE_TO_PAGES(PagedPoolSize) + (PtesPerPage - 1)) / PtesPerPage); /* Return paged pool size */ *PoolSize = PteCount * PtesPerPage; } /** * Calculates the size of the session space. * * @param SpaceSize * A pointer to a variable that will receive the number of pages available by the session space. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::ComputeSessionSpaceSize(OUT PPFN_NUMBER SpaceSize) { PFN_NUMBER SessionSpaceSize; /* Session Pool, Session View, Session Image, Session Working Set and System View takes 1120MiB */ SessionSpaceSize = 1174405120; /* Return number of pages used by the session space */ *SpaceSize = SessionSpaceSize / MM_PAGE_SIZE; } /** * Calculates the size of the system PTEs. * * @param PteSize * A pointer to a variable that will receive the number of system PTEs. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::ComputeSystemPteSize(OUT PPFN_NUMBER PteSize) { PFN_NUMBER SystemPteSize; /* Check if system has less than 24MiB of physical memory */ if(MM::Pfn::GetNumberOfPhysicalPages() < 6144) { /* Set minimal system PTE size */ SystemPteSize = 7000; } else { /* Use standard system PTE size */ SystemPteSize = 11000; /* Check if system has more than 32MiB of physical memory */ if(MM::Pfn::GetNumberOfPhysicalPages() > 8192) { /* Double system PTE size */ SystemPteSize *= 2; /* Check if system has more than 256MiB of physical memory */ if(MM::Pfn::GetNumberOfPhysicalPages() > 65536) { /* Double system PTE size */ SystemPteSize *= 2; } } } /* Return system PTE size */ *PteSize = SystemPteSize; } /** * Dumps the kernel's memory layout. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::DumpMemoryLayout(VOID) { /* Dump memory layout */ DebugPrint(L"System with %zu MiB of installed memory:\n" L"User Space: %.16P - %.16P\n" L"Non-Canonical: %.16P - %.16P\n" L"Reserved System Pool: %.16P - %.16P\n" L"PTE Space: %.16P - %.16P\n" L"Hyper Space: %.16P - %.16P\n" L"Shared System Page: %.16P - %.16P\n" L"System Working Set: %.16P - %.16P\n" L"Loader Mappings: %.16P - %.16P\n" L"Non-Paged System Pool: %.16P - %.16P\n" L"Paged Pool: %.16P - %.16P\n" L"Session Space: %.16P - %.16P\n" L"System Cache: %.16P - %.16P\n" L"PFN Database: %.16P - %.16P\n" L"Non-Paged Pool: %.16P - %.16P\n" L"Non-Paged Expansion Pool: %.16P - %.16P\n" L"Hardware Pool: %.16P - %.16P\n", GetInstalledMemorySize(), MemoryLayout.UserSpaceStart, MemoryLayout.UserSpaceEnd, MemoryLayout.NonCanonicalStart, MemoryLayout.NonCanonicalEnd, MemoryLayout.ReservedSystemPoolStart, MemoryLayout.ReservedSystemPoolEnd, MemoryLayout.PteSpaceStart, MemoryLayout.PteSpaceEnd, MemoryLayout.HyperSpaceStart, MemoryLayout.HyperSpaceEnd, MemoryLayout.SharedSystemPageStart, MemoryLayout.SharedSystemPageEnd, MemoryLayout.SystemWorkingSetStart, MemoryLayout.SystemWorkingSetEnd, MemoryLayout.LoaderMappingsStart, MemoryLayout.LoaderMappingsEnd, MemoryLayout.NonPagedSystemPoolStart, MemoryLayout.NonPagedSystemPoolEnd, MemoryLayout.PagedPoolStart, MemoryLayout.PagedPoolEnd, MemoryLayout.SessionSpaceStart, MemoryLayout.SessionSpaceEnd, MemoryLayout.SystemCacheStart, MemoryLayout.SystemCacheEnd, MemoryLayout.PfnDatabase, (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + (ULONG_PTR)MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE), MemoryLayout.NonPagedPoolStart, MemoryLayout.NonPagedPoolEnd, MemoryLayout.NonPagedExpansionPoolStart, MemoryLayout.NonPagedExpansionPoolEnd, MemoryLayout.HardwarePoolStart, MemoryLayout.HardwarePoolEnd); } /** * Initializes the kernel's virtual memory layout. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::InitializeMemoryLayout(VOID) { PFN_NUMBER MaximumNonPagedPoolSize; ULONG_PTR PfnDatabaseEnd; /* Check if 5-level paging (LA57) is enabled */ if(MM::Paging::GetXpaStatus()) { /* Set PML5 base address */ MemoryLayout.SelfMapAddress = (PVOID)MM_P5E_LA57_BASE; /* Define memory layout for 5-level paging */ MemoryLayout.UserSpaceStart = (PVOID)0x0000000000010000; MemoryLayout.UserSpaceEnd = (PVOID)0x00FFFFFFFFFEFFFF; MemoryLayout.NonCanonicalStart = (PVOID)0x0080000000000000; MemoryLayout.NonCanonicalEnd = (PVOID)0xFEFFFFFFFFFFFFFF; MemoryLayout.ReservedSystemPoolStart = (PVOID)0xFF00000000000000; MemoryLayout.ReservedSystemPoolEnd = (PVOID)0xFFECFFFFFFFFFFFF; MemoryLayout.PteSpaceStart = (PVOID)0xFFED000000000000; MemoryLayout.PteSpaceEnd = (PVOID)0xFFEDFFFFFFFFFFFF; MemoryLayout.HyperSpaceStart = (PVOID)0xFFFFF70000000000; MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFFF77FFFFFFFFF; MemoryLayout.SharedSystemPageStart = (PVOID)0xFFFFF78000000000; MemoryLayout.SharedSystemPageEnd = (PVOID)0xFFFFF78000000FFF; MemoryLayout.SystemWorkingSetStart = (PVOID)0xFFFFF78000001000; MemoryLayout.SystemWorkingSetEnd = (PVOID)0xFFFFF7FFFFFFFFFF; MemoryLayout.LoaderMappingsStart = (PVOID)0xFFFFF80000000000; MemoryLayout.LoaderMappingsEnd = (PVOID)0xFFFFF87FFFFFFFFF; MemoryLayout.NonPagedSystemPoolStart = (PVOID)0xFFFFF88000000000; MemoryLayout.NonPagedSystemPoolEnd = (PVOID)0xFFFFF89FFFFFFFFF; MemoryLayout.PagedPoolStart = (PVOID)0xFFFFF8A000000000; MemoryLayout.PagedPoolEnd = (PVOID)0xFFFFF8BFFFFFFFFF; MemoryLayout.SessionSpaceStart = (PVOID)0xFFFFF90000000000; MemoryLayout.SessionSpaceEnd = (PVOID)0xFFFFF98000000000; MemoryLayout.SystemCacheStart = (PVOID)0xFFFFF98000000000; MemoryLayout.SystemCacheEnd = (PVOID)0xFFFFFA7FFFFFFFFF; MemoryLayout.NonPagedPoolStart = (PVOID)0xFFFFFA8000000000; MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFFFFFFFFBFFFFF; MemoryLayout.HardwarePoolStart = (PVOID)0xFFFFFFFFFFC00000; MemoryLayout.HardwarePoolEnd = (PVOID)0xFFFFFFFFFFFFFFFF; } else { /* Set PML4 base address */ MemoryLayout.SelfMapAddress = (PVOID)MM_PXE_BASE; /* Define memory layout for 4-level paging */ MemoryLayout.UserSpaceStart = (PVOID)0x0000000000010000; MemoryLayout.UserSpaceEnd = (PVOID)0x000007FFFFFEFFFF; MemoryLayout.NonCanonicalStart = (PVOID)0x0000800000000000; MemoryLayout.NonCanonicalEnd = (PVOID)0xFFFF7FFFFFFFFFFF; MemoryLayout.ReservedSystemPoolStart = (PVOID)0xFFFF800000000000; MemoryLayout.ReservedSystemPoolEnd = (PVOID)0xFFFFF67FFFFFFFFF; MemoryLayout.PteSpaceStart = (PVOID)0xFFFFF68000000000; MemoryLayout.PteSpaceEnd = (PVOID)0xFFFFF6FFFFFFFFFF; MemoryLayout.HyperSpaceStart = (PVOID)0xFFFFF70000000000; MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFFF77FFFFFFFFF; MemoryLayout.SharedSystemPageStart = (PVOID)0xFFFFF78000000000; MemoryLayout.SharedSystemPageEnd = (PVOID)0xFFFFF78000000FFF; MemoryLayout.SystemWorkingSetStart = (PVOID)0xFFFFF78000001000; MemoryLayout.SystemWorkingSetEnd = (PVOID)0xFFFFF7FFFFFFFFFF; MemoryLayout.LoaderMappingsStart = (PVOID)0xFFFFF80000000000; MemoryLayout.LoaderMappingsEnd = (PVOID)0xFFFFF87FFFFFFFFF; MemoryLayout.NonPagedSystemPoolStart = (PVOID)0xFFFFF88000000000; MemoryLayout.NonPagedSystemPoolEnd = (PVOID)0xFFFFF89FFFFFFFFF; MemoryLayout.PagedPoolStart = (PVOID)0xFFFFF8A000000000; MemoryLayout.PagedPoolEnd = (PVOID)0xFFFFF8BFFFFFFFFF; MemoryLayout.SessionSpaceStart = (PVOID)0xFFFFF90000000000; MemoryLayout.SessionSpaceEnd = (PVOID)0xFFFFF98000000000; MemoryLayout.SystemCacheStart = (PVOID)0xFFFFF98000000000; MemoryLayout.SystemCacheEnd = (PVOID)0xFFFFFA7FFFFFFFFF; MemoryLayout.NonPagedPoolStart = (PVOID)0xFFFFFA8000000000; MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFFFFFFFFBFFFFF; MemoryLayout.HardwarePoolStart = (PVOID)0xFFFFFFFFFFC00000; MemoryLayout.HardwarePoolEnd = (PVOID)0xFFFFFFFFFFFFFFFF; } /* Compute allocation size for the PFN database */ MM::Pfn::ComputePfnDatabaseSize(&MemoryLayout.PfnDatabaseSize); /* Compute boot image size */ ComputeBootImageSize(&MemoryLayout.LoaderMappingsSize); /* Compute session space size */ ComputeSessionSpaceSize(&MemoryLayout.SessionSpaceSize); /* Update loader mappings space end address */ MemoryLayout.LoaderMappingsEnd = (PVOID)((ULONGLONG)MemoryLayout.LoaderMappingsStart + MemoryLayout.LoaderMappingsSize * MM_PAGE_SIZE); /* Update session space start address */ MemoryLayout.SessionSpaceStart = (PVOID)((ULONGLONG)MemoryLayout.SessionSpaceEnd - MemoryLayout.SessionSpaceSize * MM_PAGE_SIZE); /* Compute system PTE size */ ComputeSystemPteSize(&NumberOfSystemPtes); /* Compute non-paged pool size */ ComputeNonPagedPoolSize(&MemoryLayout.NonPagedPoolSize); ComputeMaximumNonPagedPoolSize(&MaximumNonPagedPoolSize); /* Compute paged pool size */ ComputePagedPoolSize(&MemoryLayout.PagedPoolSize); /* Insert the PFN database at the beginning of the non-paged pool */ MemoryLayout.PfnDatabase = (PMMPFN)MemoryLayout.NonPagedPoolStart; /* Compute the PFN database page-aligned end address */ PfnDatabaseEnd = (ULONGLONG)MemoryLayout.PfnDatabase + (MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); PfnDatabaseEnd = ROUND_UP(PfnDatabaseEnd, MM_PAGE_SIZE); /* Shrink the non-paged pool to fit the PFN database */ MemoryLayout.NonPagedPoolStart = (PVOID)PfnDatabaseEnd; /* Assign the rest of the non-paged pool to the expansion pool */ MemoryLayout.NonPagedExpansionPoolStart = (PVOID)((ULONGLONG)MemoryLayout.NonPagedPoolStart + MemoryLayout.NonPagedPoolSize * MM_PAGE_SIZE); MemoryLayout.NonPagedPoolEnd = MemoryLayout.NonPagedExpansionPoolStart; MemoryLayout.NonPagedExpansionPoolEnd = (PVOID)((ULONGLONG)MemoryLayout.NonPagedPoolStart + MaximumNonPagedPoolSize * MM_PAGE_SIZE); MemoryLayout.NonPagedExpansionPoolSize = ((ULONGLONG)MemoryLayout.NonPagedExpansionPoolEnd - (ULONGLONG)MemoryLayout.NonPagedExpansionPoolStart) / MM_PAGE_SIZE; /* Update paged pool end address */ MemoryLayout.PagedPoolEnd = (PVOID)(((ULONGLONG)MemoryLayout.PagedPoolStart + MemoryLayout.PagedPoolSize * MM_PAGE_SIZE) - 1); } ================================================ FILE: xtoskrnl/mm/amd64/pagemap.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/i686/pagemap.cc * DESCRIPTION: Low-level support for i686 page map manipulation * DEVELOPERS: Aiken Harris */ #include /** * Advances a PTE pointer by a given number of entries, considering the actual PTE size. * * @param Pte * The PTE pointer to advance. * * @param Count * The number of PTE entries to advance by. * * @return The advanced PTE pointer. * * @since XT 1.0 */ XTAPI PMMPTE MM::PageMap::AdvancePte(IN PMMPTE Pte, IN LONG Count) { /* Return advanced PTE pointer */ return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPTE))); } /** * Checks if the given address is canonical. * * @param VirtualAddress * Specifies the virtual address to check. * * @return This routine returns TRUE if the address is canonical, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::PageMap::CanonicalAddress(IN PVOID VirtualAddress) { ULONG Shift; /* Calculate the number of unused upper bits based on the paging mode */ Shift = 64 - PageMapInfo.VaBits; /* Sign-extend via arithmetic shifts to verify the canonical form */ return ((((LONGLONG)VirtualAddress << Shift) >> Shift) == (LONGLONG)VirtualAddress); } /** * Clears the contents of a page table entry (PTE). * * @param PtePointer * Pointer to the page table entry (PTE) to be cleared. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMap::ClearPte(IN PMMPTE PtePointer) { /* Clear PTE */ PtePointer->Long = 0; } /** * Gets the next entry in a PTE list. * * @param Pte * The PTE pointer to get the next entry from. * * @return This routine returns the next entry in the PTE list. * * @since XT 1.0 */ XTAPI ULONG_PTR MM::PageMap::GetNextEntry(IN PMMPTE Pte) { /* Return next entry in PTE list */ return Pte->List.NextEntry; } /** * Advances a PTE pointer, considering the actual PTE size. * * @param Pte * The PTE pointer to advance. * * @return The advanced PTE pointer. * * @since XT 1.0 */ XTAPI PMMPTE MM::PageMap::GetNextPte(IN PMMPTE Pte) { /* Return advanced PTE pointer */ return AdvancePte(Pte, 1); } /** * Checks if a PTE list contains only one entry. * * @param Pte * The PTE pointer to check. * * @return This routine returns TRUE if the PTE list has only one entry, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::PageMap::GetOneEntry(IN PMMPTE Pte) { /* Return one entry status */ return Pte->List.OneEntry; } /** * Gets the address of the P5E (Page Map Level 5 Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding P5E. * * @return This routine returns the address of the P5E, or NULLPTR if LA57 is not enabled. * * @since XT 1.0 */ XTAPI PMMP5E MM::PageMap::GetP5eAddress(IN PVOID Address) { ULONGLONG Offset; /* Calculate offset and return P5E address */ Offset = ((((ULONGLONG)Address & (((ULONGLONG)1 << PageMapInfo.VaBits) - 1)) >> MM_P5I_SHIFT) << MM_PTE_SHIFT); return (PMMP5E)((PageMapInfo.P5eBase + Offset) * PageMapInfo.Xpa); } /** * Gets the Offset of the P5E (Page Map Level 5 Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding P5E. * * @return This routine returns the Offset of the P5E, or NULLPTR if LA57 is not enabled. * * @since XT 1.0 */ XTAPI ULONG MM::PageMap::GetP5eOffset(IN PVOID Address) { /* Return P5E Offset */ return (((((ULONGLONG)Address) >> MM_P5I_SHIFT) & 0x1FF) * PageMapInfo.Xpa); } /** * Gets the virtual address that is mapped by a given Page Map Level 5 Entry. * * @param P5ePointer * Specifies the address of the P5E. * * @return This routine returns the virtual address mapped by the P5E, or NULLPTR if LA57 is not enabled. * * @since XT 1.0 */ XTAPI PVOID MM::PageMap::GetP5eVirtualAddress(IN PMMP5E P5ePointer) { return (PVOID)((((LONGLONG)P5ePointer << 52) >> 7) * PageMapInfo.Xpa); } /** * Gets the page frame number from a corresponding PTE. * * @param Pte * The PTE pointer to get the page frame number from. * * @return This routine returns the page frame number. * * @since XT 1.0 */ XTAPI PFN_NUMBER MM::PageMap::GetPageFrameNumber(IN PMMPTE Pte) { return Pte->Hardware.PageFrameNumber; } /** * Gets Page Map Level (PML) for current paging mode. * * @return This routine returns the page map level. * * @since XT 1.0 */ XTAPI USHORT MM::PageMap::GetPageMapLevel() { return PageMapInfo.Xpa ? 5 : 4; } /** * Gets the address of the PDE (Page Directory Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PDE. * * @return This routine returns the address of the PDE. * * @since XT 1.0 */ XTAPI PMMPDE MM::PageMap::GetPdeAddress(IN PVOID Address) { ULONGLONG Offset; /* Calculate offset and return PDE address */ Offset = ((((ULONGLONG)Address & (((ULONGLONG)1 << PageMapInfo.VaBits) - 1)) >> MM_PDI_SHIFT) << MM_PTE_SHIFT); return (PMMPDE)(PageMapInfo.PdeBase + Offset); } /** * Gets the Offset of the PDE (Page Directory Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PDE. * * @return This routine returns the Offset of the PDE. * * @since XT 1.0 */ XTAPI ULONG MM::PageMap::GetPdeOffset(IN PVOID Address) { /* Return PDE Offset */ return ((((ULONGLONG)Address) >> MM_PDI_SHIFT) & 0x1FF); } /** * Gets the address of the PPE (Page Directory Pointer Table Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PPE. * * @return This routine returns the address of the PPE. * * @since XT 1.0 */ XTAPI PMMPPE MM::PageMap::GetPpeAddress(IN PVOID Address) { ULONGLONG Offset; /* Calculate offset and return PPE address */ Offset = ((((ULONGLONG)Address & (((ULONGLONG)1 << PageMapInfo.VaBits) - 1)) >> MM_PPI_SHIFT) << MM_PTE_SHIFT); return (PMMPPE)(PageMapInfo.PpeBase + Offset); } /** * Gets the Offset of the PPE (Page Directory Pointer Table Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PPE. * * @return This routine returns the Offset of the PPE. * * @since XT 1.0 */ XTAPI ULONG MM::PageMap::GetPpeOffset(IN PVOID Address) { /* Return PPE Offset */ return ((((ULONGLONG)Address) >> MM_PPI_SHIFT) & 0x1FF); } /** * Gets the entire contents of a Page Table Entry (PTE) as a single value. * * @param PtePointer * Pointer to the Page Table Entry (PTE) to read. * * @return This routine returns the contents of the PTE as a single value. * * @since XT 1.0 */ XTAPI ULONGLONG MM::PageMap::GetPte(IN PMMPTE PtePointer) { /* Return PTE value */ return PtePointer->Long; } /** * Gets the address of the PTE (Page Table Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PTE. * * @return This routine returns the address of the PTE. * * @since XT 1.0 */ XTAPI PMMPTE MM::PageMap::GetPteAddress(IN PVOID Address) { ULONGLONG Offset; /* Calculate offset and return PTE address */ Offset = ((((ULONGLONG)Address & (((ULONGLONG)1 << PageMapInfo.VaBits) - 1)) >> MM_PTI_SHIFT) << MM_PTE_SHIFT); return (PMMPTE)(PageMapInfo.PteBase + Offset); } /** * Calculates the distance between two PTE pointers. * * @param EndPte * Pointer to the ending Page Table Entry. * * @param StartPte * Pointer to the starting Page Table Entry. * * @return This routine returns a signed value representing the number of PTEs between EndPte and StartPte. * * @since XT 1.0 */ XTAPI LONG MM::PageMap::GetPteDistance(PMMPTE EndPte, PMMPTE StartPte) { /* Return distance between PTE pointers */ return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPTE); } /** * Gets the Offset of the PTE (Page Table Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PTE. * * @return This routine returns the Offset of the PTE. * * @since XT 1.0 */ XTAPI ULONG MM::PageMap::GetPteOffset(IN PVOID Address) { /* Return PTE Offset */ return ((((ULONGLONG)Address) >> MM_PTI_SHIFT) & 0x1FF); } /** * Gets the size of a PTE. * * @return This routine returns the size of a PTE. * * @since XT 1.0 */ XTAPI ULONG MM::PageMap::GetPteSize(VOID) { /* Return the size of MMPTE */ return sizeof(MMPTE); } /** * Gets the software protection value of the corresponding Page Table Entry. * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the PTE software protection value. * * @since XT 1.0 */ XTAPI ULONG MM::PageMap::GetPteSoftwareProtection(IN PMMPTE PtePointer) { /* Return PTE software protection value */ return (ULONG)PtePointer->Software.Protection; } /** * Gets the software prototype value of the corresponding Page Table Entry. * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the PTE software prototype value. * * @since XT 1.0 */ XTAPI ULONG MM::PageMap::GetPteSoftwarePrototype(IN PMMPTE PtePointer) { /* Return PTE software prototype value */ return (ULONG)PtePointer->Software.Prototype; } /** * Gets the software transition value of the corresponding Page Table Entry. * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the PTE software transition value. * * @since XT 1.0 */ XTAPI ULONG MM::PageMap::GetPteSoftwareTransition(IN PMMPTE PtePointer) { /* Return PTE software transition value */ return (ULONG)PtePointer->Software.Transition; } /** * Gets the address of the PXE (Extended Page Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PXE. * * @return This routine returns the address of the PXE. * * @since XT 1.0 */ XTAPI PMMPXE MM::PageMap::GetPxeAddress(IN PVOID Address) { ULONGLONG Offset; /* Calculate offset and return PXE address */ Offset = ((((ULONGLONG)Address & (((ULONGLONG)1 << PageMapInfo.VaBits) - 1)) >> MM_PXI_SHIFT) << MM_PTE_SHIFT); return (PMMPXE)(PageMapInfo.PxeBase + Offset); } /** * Gets the Offset of the PXE (Extended Page Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PXE. * * @return This routine returns the Offset of the PXE. * * @since XT 1.0 */ XTAPI ULONG MM::PageMap::GetPxeOffset(IN PVOID Address) { /* Return PXE Offset */ return ((((ULONGLONG)Address) >> MM_PXI_SHIFT) & 0x1FF); } /** * Gets the status of Extended Paging Address (XPA) mode. * * @return This routine returns TRUE if XPA is enabled, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::PageMap::GetXpaStatus() { return PageMapInfo.Xpa; } /** * Checks whether the given PML2 page table entry (PTE) is valid. * * @param PtePointer * Pointer to the page table entry (PTE) to check. * * @return Returns TRUE if the entry is valid, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::PageMap::PteValid(IN PMMPTE PtePointer) { /* Check if PTE is valid */ return (BOOLEAN)PtePointer->Hardware.Valid; } /** * Sets the next entry in a PTE list. * * @param Pte * The PTE pointer to modify. * * @param Value * The value to set as the next entry. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMap::SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value) { /* Set next entry in PTE list */ Pte->List.NextEntry = Value; } /** * Sets the flag indicating whether a PTE list contains only one entry. * * @param Pte * The PTE pointer to modify. * * @param Value * The value to set. TRUE if the list has only one entry, FALSE otherwise. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMap::SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value) { /* Set one entry status */ Pte->List.OneEntry = Value; } /** * Sets a Page Table Entry (PTE) with the specified physical page and access flags. * * @param PtePointer * Pointer to the page table entry (PTE) to set. * * @param PageFrameNumber * Physical frame number to map. * * @param AttributesMask * Specifies the attributes mask to apply to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMap::SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG AttributesMask) { /* Set PTE */ PtePointer->Hardware.PageFrameNumber = PageFrameNumber; PtePointer->Hardware.Valid = 1; PtePointer->Long |= AttributesMask; } /** * Sets a Page Table Entry (PTE) with the specified attributes. * * @param PtePointer * Pointer to the page table entry (PTE) to set. * * @param Attributes * Specifies the attributes to apply to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMap::SetPte(IN PMMPTE PtePointer, IN ULONGLONG Attributes) { PtePointer->Long = Attributes; } /** * Sets caching attributes for a PML2 page table entry (PTE). * * @param PtePointer * Pointer to the page table entry (PTE) to modify. * * @param CacheDisable * Indicates whether caching should be disabled for this page. * * @param WriteThrough * Indicates whether write-through caching should be enabled. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMap::SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) { /* Set caching attributes */ PtePointer->Hardware.CacheDisable = CacheDisable; PtePointer->Hardware.WriteThrough = WriteThrough; } /** * Transitions a Page Table Entry (PTE) to invalid state * * @param PointerPte * Pointer to the page table entry (PTE) to transition. * * @param Protection * Specifies the protection attribute to apply to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMap::TransitionPte(IN PMMPTE PointerPte, IN ULONG_PTR Protection) { MMPTE TempPte; /* Set transition PTE */ TempPte = *PointerPte; TempPte.Software.Protection = Protection; TempPte.Software.Prototype = 0; TempPte.Software.Transition = 1; TempPte.Software.Valid = 0; /* Write PTE value */ *PointerPte = TempPte; } /** * Writes a Page Table Entry (PTE) with the specified value. * * @param Pte * Pointer to the page table entry (PTE) to write. * * @param Value * The value to write to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMap::WritePte(IN PMMPTE Pte, IN MMPTE Value) { /* Write PTE value */ Pte->Long = Value.Long; } /** * Gets the virtual address that is mapped by a given Page Directory Entry (PML4). * * @param PdePointer * Specifies the address of the PDE. * * @return This routine returns the virtual address mapped by the PDE. * * @since XT 1.0 */ XTAPI PVOID MM::PageMapBasic::GetPdeVirtualAddress(IN PMMPDE PdePointer) { /* Return PDE virtual address */ return (PVOID)(((LONGLONG)PdePointer << 34) >> 16); } /** * Gets the virtual address that is mapped by a given Page Directory Pointer Table Entry (PML4). * * @param PpePointer * Specifies the address of the PPE. * * @return This routine returns the virtual address mapped by the PPE. * * @since XT 1.0 */ XTAPI PVOID MM::PageMapBasic::GetPpeVirtualAddress(IN PMMPPE PpePointer) { /* Return PPE virtual address */ return (PVOID)(((LONGLONG)PpePointer << 43) >> 16); } /** * Gets the virtual address that is mapped by a given Page Table Entry (PML4). * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the virtual address mapped by the PTE. * * @since XT 1.0 */ XTAPI PVOID MM::PageMapBasic::GetPteVirtualAddress(IN PMMPTE PtePointer) { /* Return PTE virtual address */ return (PVOID)(((LONGLONG)PtePointer << 25) >> 16); } /** * Gets the virtual address that is mapped by a given Extended Page Entry (PML4). * * @param PxePointer * Specifies the address of the PXE. * * @return This routine returns the virtual address mapped by the PXE. * * @since XT 1.0 */ XTAPI PVOID MM::PageMapBasic::GetPxeVirtualAddress(IN PMMPXE PxePointer) { /* Return PXE virtual address */ return (PVOID)(((LONGLONG)PxePointer << 52) >> 16); } /** * Initializes page map information for basic paging (PML4). * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapBasic::InitializePageMapInfo(VOID) { /* Set PML4 page map information */ PageMapInfo.Xpa = FALSE; /* Set PML4 base addresses */ PageMapInfo.PteBase = MM_PTE_BASE; PageMapInfo.PdeBase = MM_PDE_BASE; PageMapInfo.PpeBase = MM_PPE_BASE; PageMapInfo.PxeBase = MM_PXE_BASE; PageMapInfo.P5eBase = 0x0; /* PML use 48-bit virtual addresses */ PageMapInfo.VaBits = 48; } /** * Gets the virtual address that is mapped by a given Page Directory Entry (PML5). * * @param PdePointer * Specifies the address of the PDE. * * @return This routine returns the virtual address mapped by the PDE. * * @since XT 1.0 */ XTAPI PVOID MM::PageMapXpa::GetPdeVirtualAddress(IN PMMPDE PdePointer) { /* Return PDE virtual address */ return (PVOID)(((LONGLONG)PdePointer << 25) >> 7); } /** * Gets the virtual address that is mapped by a given Page Directory Pointer Table Entry (PML5). * * @param PpePointer * Specifies the address of the PPE. * * @return This routine returns the virtual address mapped by the PPE. * * @since XT 1.0 */ XTAPI PVOID MM::PageMapXpa::GetPpeVirtualAddress(IN PMMPPE PpePointer) { /* Return PPE virtual address */ return (PVOID)(((LONGLONG)PpePointer << 34) >> 7); } /** * Gets the virtual address that is mapped by a given Page Table Entry (PML5). * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the virtual address mapped by the PTE. * * @since XT 1.0 */ XTAPI PVOID MM::PageMapXpa::GetPteVirtualAddress(IN PMMPTE PtePointer) { /* Return PTE virtual address */ return (PVOID)(((LONGLONG)PtePointer << 16) >> 7); } /** * Gets the virtual address that is mapped by a given Extended Page Entry (PML5). * * @param PxePointer * Specifies the address of the PXE. * * @return This routine returns the virtual address mapped by the PXE. * * @since XT 1.0 */ XTAPI PVOID MM::PageMapXpa::GetPxeVirtualAddress(IN PMMPXE PxePointer) { /* Return PXE virtual address */ return (PVOID)(((LONGLONG)PxePointer << 43) >> 7); } /** * Initializes page map information for XPA paging (PML5). * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapXpa::InitializePageMapInfo(VOID) { /* Set PML5 page map information */ PageMapInfo.Xpa = TRUE; /* Set PML5 base addresses */ PageMapInfo.PteBase = MM_PTE_LA57_BASE; PageMapInfo.PdeBase = MM_PDE_LA57_BASE; PageMapInfo.PpeBase = MM_PPE_LA57_BASE; PageMapInfo.PxeBase = MM_PXE_LA57_BASE; PageMapInfo.P5eBase = MM_P5E_LA57_BASE; /* PML5 use 57-bit virtual addresses */ PageMapInfo.VaBits = 57; } ================================================ FILE: xtoskrnl/mm/amd64/paging.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/amd64/paging.cc * DESCRIPTION: Architecture dependent paging support * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Checks if eXtended Physical Addressing (XPA) is enabled. * * @return This routine returns TRUE if LA57 is enabled, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Paging::GetExtendedPhysicalAddressingStatus(VOID) { /* Check if LA57 is enabled */ return ((AR::CpuFunctions::ReadControlRegister(4) & CR4_LA57) != 0) ? TRUE : FALSE; } /** * Gets the address of the P5E (Page Map Level 5 Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding P5E. * * @return This routine returns the address of the P5E, or NULLPTR if LA57 is not enabled. * * @since XT 1.0 */ XTAPI PMMP5E MM::Paging::GetP5eAddress(IN PVOID Address) { /* Return PDE address */ return PmlRoutines->GetP5eAddress(Address); } /** * Gets the virtual address that is mapped by a given Page Map Level 5 Entry. * * @param P5ePointer * Specifies the address of the P5E. * * @return This routine returns the virtual address mapped by the P5E, or NULLPTR if LA57 is not enabled. * * @since XT 1.0 */ XTAPI PVOID MM::Paging::GetP5eVirtualAddress(IN PMMP5E P5ePointer) { /* Return PTE virtual address */ return PmlRoutines->GetP5eVirtualAddress(P5ePointer); } /** * Gets the address of the PXE (Extended Page Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PXE. * * @return This routine returns the address of the PXE. * * @since XT 1.0 */ XTAPI PMMPXE MM::Paging::GetPxeAddress(IN PVOID Address) { /* Return PXE address */ return PmlRoutines->GetPxeAddress(Address); } /** * Gets the virtual address that is mapped by a given Extended Page Entry. * * @param PxePointer * Specifies the address of the PXE. * * @return This routine returns the virtual address mapped by the PXE. * * @since XT 1.0 */ XTAPI PVOID MM::Paging::GetPxeVirtualAddress(IN PMMPXE PxePointer) { /* Return PXE virtual address */ return PmlRoutines->GetPxeVirtualAddress(PxePointer); } /** * Maps a specific virtual address to a specific physical page frame. * * @param VirtualAddress * The virtual address to map. * * @param PageFrameNumber * The physical frame number to back the virtual address. * * @param Attributes * Specifies the attributes (protections, caching) to apply to the PTE. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Paging::MapVirtualAddress(IN PVOID VirtualAddress, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG Attributes) { MMPTE TemplatePte; PMMPTE PointerPte; /* Initialize the template PTE */ MM::Paging::ClearPte(&TemplatePte); MM::Paging::SetPte(&TemplatePte, 0, Attributes | MM_PTE_CACHE_ENABLE); /* Check if XPA is enabled */ if(MM::Paging::GetXpaStatus()) { /* Map Page 5-level Entry*/ MM::Pte::MapP5E(VirtualAddress, VirtualAddress, (PMMP5E)&TemplatePte); } /* Map PXE, PPE and PDE for the corresponding virtual address */ MM::Pte::MapPXE(VirtualAddress, VirtualAddress, (PMMPXE)&TemplatePte); MM::Pte::MapPPE(VirtualAddress, VirtualAddress, (PMMPPE)&TemplatePte); MM::Pte::MapPDE(VirtualAddress, VirtualAddress, (PMMPDE)&TemplatePte); /* Get PTE address */ PointerPte = MM::Paging::GetPteAddress(VirtualAddress); /* Initialize the template PTE */ MM::Paging::ClearPte(&TemplatePte); MM::Paging::SetPte(&TemplatePte, PageFrameNumber, Attributes); /* Write the PTE */ MM::Paging::WritePte(PointerPte, TemplatePte); /* Flush the TLB to reflect the changes */ MM::Paging::FlushTlb(); /* Return success */ return STATUS_SUCCESS; } /** * Fills a section of memory with zeroes like RtlZeroMemory(), but in more efficient way. * * @param Address * Supplies an address of the page to be filled with zeroes. * * @param Size * Number of bytes to be filled with zeros. This always should be a multiply of page size. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID MM::Paging::ZeroPages(IN PVOID Address, IN ULONG Size) { __asm__ volatile("xor %%rax, %%rax\n" "mov %0, %%rdi\n" "mov %1, %%ecx\n" "shr $3, %%ecx\n" "rep stosq\n" : : "m" (Address), "m" (Size) : "rax", "rdi", "ecx", "memory"); } ================================================ FILE: xtoskrnl/mm/amd64/pfault.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/amd64/pfault.cc * DESCRIPTION: Page fault support for AMD64 architecture * DEVELOPERS: Aiken Harris */ #include /** * Evaluates the PDE for for paged pool and per-session mappings. * * @param VirtualAddress * Specifies the virtual address to verify. * * @return This routine returns ACCESS_VIOLATION regardless PML4 or PML5 is used. */ XTFASTCALL XTSTATUS MM::PageFault::CheckPdeForPagedPool(IN PVOID VirtualAddress) { /* Return access violation */ return STATUS_ACCESS_VIOLATION; } ================================================ FILE: xtoskrnl/mm/amd64/pfn.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/amd64/pfn.cc * DESCRIPTION: Physical Frame Number for AMD64 support * DEVELOPERS: Aiken Harris * Rafal Kupiec */ #include /** * Allocates and initializes page directory structures for a range of PDEs. * * @param StartingPde * Supplies a pointer to the first PDE in the range to initialize. * * @param EndingPde * Supplies a pointer to the last PDE in the range to initialize. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::InitializePageDirectory(IN PMMPDE StartingPde, IN PMMPDE EndingPde) { PMMPTE ParentPte, ValidPte; BOOLEAN PteValidated; /* Get a template PTE for mapping the PFN database pages */ ValidPte = MM::Pte::GetValidPte(); /* Initialize validation flag */ PteValidated = FALSE; /* Iterate through the range of PDEs to ensure the paging hierarchy is fully mapped */ while(StartingPde <= EndingPde) { /* Check if there is a need to validate upper-level page table entries */ if(!PteValidated || ((ULONG_PTR)StartingPde & (MM_PAGE_SIZE - 1)) == 0) { /* For LA57, ensure PML5 entry exists */ if(MM::Paging::GetXpaStatus()) { /* Get the P5E that maps the PXE page containing this hierarchy */ ParentPte = MM::Paging::GetPpeAddress(StartingPde); /* Check if P5E entry is valid */ if(!MM::Paging::PteValid(ParentPte)) { /* Allocate a new PML4 page and map P5E to it */ MM::Paging::SetPte(ValidPte, AllocateBootstrapPages(1), 0); *ParentPte = *ValidPte; /* Clear the newly created page */ RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(ParentPte), MM_PAGE_SIZE); } } /* Get the PXE that maps the PPE page containing PDE */ ParentPte = MM::Paging::GetPdeAddress(StartingPde); /* Check if PXE entry is valid */ if(!MM::Paging::PteValid(ParentPte)) { /* Allocate a new PPE page and map PXE to it */ MM::Paging::SetPte(ValidPte, AllocateBootstrapPages(1), 0); *ParentPte = *ValidPte; /* Clear the newly created page */ RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(ParentPte), MM_PAGE_SIZE); } /* Get the PPE that maps the PDE page containing PTE */ ParentPte = MM::Paging::GetPteAddress(StartingPde); /* Check if PPE entry is valid */ if(!MM::Paging::PteValid(ParentPte)) { /* Allocate a new PDE page and map PPE to it */ MM::Paging::SetPte(ValidPte, AllocateBootstrapPages(1), 0); *ParentPte = *ValidPte; /* Clear the newly created page */ RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(ParentPte), MM_PAGE_SIZE); } /* Upper levels for this PDE have been validated */ PteValidated = TRUE; } /* Ensure the PDE has a PTE page allocated */ if(!MM::Paging::PteValid(StartingPde)) { /* Allocate a new PTE page and map PDE to it */ MM::Paging::SetPte(ValidPte, AllocateBootstrapPages(1), 0); *StartingPde = *ValidPte; /* Clear the newly created page */ RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(StartingPde), MM_PAGE_SIZE); } /* Move to the next PDE */ StartingPde = MM::Paging::GetNextPte(StartingPde); } } /** * Initializes the PFN database by mapping virtual memory and populating entries. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::InitializePfnDatabase(VOID) { PKERNEL_INITIALIZATION_BLOCK InitializationBlock; PLIST_ENTRY ListEntry; PLOADER_MEMORY_DESCRIPTOR Descriptor; PUCHAR PfnDatabaseEnd; PMMMEMORY_LAYOUT MemoryLayout; PMMPTE ValidPte; /* Raise runlevel and acquire the PFN lock */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); /* Get the kernel initialization block */ InitializationBlock = KE::BootInformation::GetInitializationBlock(); /* Get the memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Get the PFN database size and calculate the end of the PFN database virtual address space */ PfnDatabaseEnd = (PUCHAR)MemoryLayout->PfnDatabase + (MemoryLayout->PfnDatabaseSize * MM_PAGE_SIZE) - 1; /* Get a template PTE for mapping the PFN database pages */ ValidPte = MM::Pte::GetValidPte(); /* Map the Page Directory and Page Directory Pointer tables for the PFN database */ MM::Pte::MapPPE(MemoryLayout->PfnDatabase, PfnDatabaseEnd, ValidPte); MM::Pte::MapPDE(MemoryLayout->PfnDatabase, PfnDatabaseEnd, ValidPte); MM::Pte::MapPTE(MemoryLayout->PfnDatabase, PfnDatabaseEnd, ValidPte); /* Zero PFN database virtual space */ RTL::Memory::ZeroMemory(MemoryLayout->PfnDatabase, MemoryLayout->PfnDatabaseSize * MM_PAGE_SIZE); /* Initialize the color tables */ MM::Colors::InitializeColorTables(); /* Iterate over memory descriptors to map the PFN database and initialize entries */ ListEntry = InitializationBlock->MemoryDescriptorListHead.Flink; while(ListEntry != &InitializationBlock->MemoryDescriptorListHead) { /* Get the descriptor */ Descriptor = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_DESCRIPTOR, ListEntry); /* Skip invisible memory regions */ if(MM::Manager::VerifyMemoryTypeInvisible(Descriptor->MemoryType)) { /* Move to the next descriptor and continue */ ListEntry = ListEntry->Flink; continue; } /* Check if this is the modified free descriptor */ if(Descriptor == FreeDescriptor) { /* Switch to the original descriptor */ Descriptor = &OriginalFreeDescriptor; } /* Check if the free memory block that was split is being processed */ if(Descriptor == &OriginalFreeDescriptor) { /* Skip loop processing, free memory is initialized separately */ ListEntry = ListEntry->Flink; continue; } /* Initialize PFNs for this memory range */ ProcessMemoryDescriptor(Descriptor->BasePage, Descriptor->PageCount, Descriptor->MemoryType); /* Move to the next descriptor */ ListEntry = ListEntry->Flink; } /* Initialize PFNs for the free memory */ ProcessMemoryDescriptor(FreeDescriptor->BasePage, FreeDescriptor->PageCount, LoaderFree); /* Initialize PFNs for the physical pages backing the PFN database */ ProcessMemoryDescriptor(OriginalFreeDescriptor.BasePage, FreeDescriptor->BasePage - OriginalFreeDescriptor.BasePage, LoaderMemoryData); /* Restore original free descriptor */ *FreeDescriptor = OriginalFreeDescriptor; /* Initialize PFNs backing page tables */ InitializePageTablePfns(); } /** * Initializes PFN database entries for the system page tables. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::InitializePageTablePfns(VOID) { PFN_NUMBER PageFrameIndex; PMMPFN Pfn; ULONG RootLevel; PMMPTE RootPte; /* Determine root structure based on paging mode */ if(MM::Paging::GetXpaStatus()) { /* XPA enabled, 5-level paging (LA57) */ RootLevel = 5; /* Retrieve the PFN of the PML5 table and its virtual base address */ PageFrameIndex = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress((PVOID)MM_P5E_LA57_BASE)); RootPte = (PMMPTE)MM::Paging::GetP5eAddress(NULLPTR); } else { /* XPA disabled, 4-level paging */ RootLevel = 4; /* Retrieve the PFN of the PML4 table and its virtual base address */ PageFrameIndex = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress((PVOID)MM_PXE_BASE)); RootPte = (PMMPTE)MM::Paging::GetPxeAddress(NULLPTR); } /* Initialize the PFN entry for the root page table itself */ Pfn = GetPfnEntry(PageFrameIndex); if(Pfn) { /* Initialize the PFN entry */ Pfn->PteAddress = NULLPTR; Pfn->u1.WsIndex = 0; Pfn->u2.ShareCount = 1; Pfn->u3.e1.CacheAttribute = PfnNonCached; Pfn->u3.e2.ReferenceCount = 1; Pfn->u4.PteFrame = 0; } /* Start recursive scan from the top level */ if(RootPte) { /* Scan the root page table */ ScanPageTable(RootPte, RootLevel); } } /** * Recursively scans a page table to initialize PFN database entries for active pages. * * @param PointerPte * Pointer to the base of the page table to scan. * * @param Level * The paging level of the table being scanned. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::ScanPageTable(IN PMMPTE PointerPte, IN ULONG Level) { PVOID Address; ULONG Index; PMMPTE NextLevelPte; ULONG PtesPerPage; /* Get the number of PTEs per page */ PtesPerPage = MM::Pte::GetPtesPerPage(); /* Iterate through all entries in the current page table */ for(Index = 0; Index < PtesPerPage; Index++) { /* Check if the page table entry is present */ if(MM::Paging::PteValid(PointerPte)) { /* Mark the PFN pointed to by this entry as active */ LinkPfnForPageTable(MM::Paging::GetPageFrameNumber(PointerPte), PointerPte); /* Recurse to the next level, if this is not a leaf node (PTE) */ if(Level > 1) { /* Calculate the virtual address mapped by this entry to find the next table */ switch(Level) { case 5: /* Calculate PXE */ Address = MM::Paging::GetP5eVirtualAddress((PMMP5E)PointerPte); NextLevelPte = (PMMPTE)MM::Paging::GetPxeAddress(Address); break; case 4: /* Calculate PPE */ Address = MM::Paging::GetPxeVirtualAddress((PMMPXE)PointerPte); NextLevelPte = (PMMPTE)MM::Paging::GetPpeAddress(Address); break; case 3: /* Calculate PDE */ Address = MM::Paging::GetPpeVirtualAddress((PMMPPE)PointerPte); NextLevelPte = (PMMPTE)MM::Paging::GetPdeAddress(Address); break; case 2: /* Calculate PTE */ Address = MM::Paging::GetPdeVirtualAddress((PMMPDE)PointerPte); NextLevelPte = MM::Paging::GetPteAddress(Address); break; default: /* Nothing to calculate, return NULLPTR */ NextLevelPte = NULLPTR; break; } /* Recurse deeper if not at the bottom level (PTE) already */ if(NextLevelPte) { /* Recursively scan the next level page table */ ScanPageTable(NextLevelPte, Level - 1); } } } /* Move to the next entry in the current table */ PointerPte = MM::Paging::GetNextPte(PointerPte); } } ================================================ FILE: xtoskrnl/mm/amd64/pool.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/amd64/pool.cc * DESCRIPTION: AMD64 Memory Manager pool manager * DEVELOPERS: Aiken Harris */ #include /** * Maps the PTE for the base of the non-paged pool. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::MapNonPagedPool(VOID) { PMMMEMORY_LAYOUT MemoryLayout; /* Retrieve memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Map PPE and PDE for whole non-paged pool */ MM::Pte::MapPPE(MemoryLayout->NonPagedPoolStart, MemoryLayout->NonPagedExpansionPoolEnd, MM::Pte::GetValidPte()); MM::Pte::MapPDE(MemoryLayout->NonPagedPoolStart, MemoryLayout->NonPagedExpansionPoolEnd, MM::Pte::GetValidPte()); /* Map PTE only for the base of the non-paged pool */ MM::Pte::MapPTE(MemoryLayout->NonPagedPoolStart, (PCHAR)MemoryLayout->NonPagedPoolEnd - 1, MM::Pte::GetValidPte()); } ================================================ FILE: xtoskrnl/mm/amd64/pte.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/amd64/pte.cc * DESCRIPTION: Page Table Entry (PTE) for AMD64 support * DEVELOPERS: Aiken Harris */ #include /** * Checks if the virtual address is valid and mapped in the page tables. * * @param VirtualAddress * The virtual address to check. * * @return This routine returns TRUE if the address is valid, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Pte::AddressValid(IN PVOID VirtualAddress) { /* Check XPA status */ if(MM::Paging::GetXpaStatus()) { /* Check if the P5E is valid */ if(!MM::Paging::PteValid(MM::Paging::GetP5eAddress(VirtualAddress))) { /* Invalid P5E, return FALSE */ return FALSE; } } /* Check if PXE, PPE, PDE and PTE are valid */ if(!MM::Paging::PteValid(MM::Paging::GetPxeAddress(VirtualAddress)) || !MM::Paging::PteValid(MM::Paging::GetPpeAddress(VirtualAddress)) || !MM::Paging::PteValid(MM::Paging::GetPdeAddress(VirtualAddress)) || !MM::Paging::PteValid(MM::Paging::GetPteAddress(VirtualAddress))) { /* Invalid PXE, PPE, PDE or PTE, return FALSE */ return FALSE; } /* Address is valid, return TRUE */ return TRUE; } /** * Retrieves the base virtual address of the system PTEs. * * @return This routine returns a pointer to the first PTE in the system PTE space. * * @since XT 1.0 */ XTAPI PMMPTE MM::Pte::GetSystemPteBaseAddress(VOID) { PMMMEMORY_LAYOUT MemoryLayout; /* Retrieve the system's memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Determine the base address for system PTEs based on the paging mode */ if(MM::Paging::GetXpaStatus()) { /* For 5-level paging, system PTEs start at the beginning of system space */ return MM::Paging::GetPteAddress((PVOID)MemoryLayout->NonPagedSystemPoolStart); } else { /* For 4-level paging, system PTEs start at the legacy KSEG0_BASE */ return MM::Paging::GetPteAddress((PVOID)KSEG0_BASE); } } /** * Performs the initial setup of the system's page table hierarchy. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pte::InitializePageTable(VOID) { PMMPTE EndSpacePte, PointerPte; PMMMEMORY_LAYOUT MemoryLayout; PVOID MappingRange; MMPTE TemplatePte; BOOLEAN Xpa; /* Retrieve current paging mode and memory layout */ Xpa = MM::Paging::GetXpaStatus(); MemoryLayout = MM::Manager::GetMemoryLayout(); /* Enable the Global Paging (PGE) feature */ AR::CpuFunctions::WriteControlRegister(4, AR::CpuFunctions::ReadControlRegister(4) | CR4_PGE); /* Check XPA status */ if(Xpa) { /* Get the PML5 user-space range if 5-level paging is active */ PointerPte = MM::Paging::GetP5eAddress(0); EndSpacePte = MM::Paging::GetP5eAddress(MemoryLayout->UserSpaceEnd); } else { /* Otherwise, get the PML4 user-space range for 4-level paging */ PointerPte = MM::Paging::GetPxeAddress(0); EndSpacePte = MM::Paging::GetPxeAddress(MemoryLayout->UserSpaceEnd); } /* Clear all top-level entries mapping the user address space */ while(PointerPte <= EndSpacePte) { MM::Paging::ClearPte(PointerPte); PointerPte = MM::Paging::GetNextPte(PointerPte); } /* Flush the TLB to invalidate all non-global entries */ AR::CpuFunctions::FlushTlb(); /* Create a template PTE for mapping kernel pages */ MM::Paging::ClearPte(&TemplatePte); MM::Paging::SetPte(&TemplatePte, 0, MM_PTE_READWRITE | MM_PTE_CACHE_ENABLE); /* Check XPA status */ if(Xpa) { /* Map the kernel's PML5 entries if 5-level paging is active */ MM::Pte::MapP5E(MemoryLayout->HyperSpaceStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte); } /* Map the kernel's PML4 entries */ MM::Pte::MapPXE(MemoryLayout->HyperSpaceStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte); /* Calculate the end address of the hyperspace working set mapping */ MappingRange = (PVOID)((ULONG_PTR)MemoryLayout->HyperSpaceStart + MM_HYPERSPACE_PAGE_COUNT * MM_PAGE_SIZE); /* Map the PDPT entries for paged pool and hyperspace */ MM::Pte::MapPPE(MemoryLayout->PagedPoolStart, MemoryLayout->PagedPoolEnd, &ValidPte); MM::Pte::MapPPE(MemoryLayout->HyperSpaceStart, MemoryLayout->HyperSpaceEnd, &ValidPte); /* Map the PDEs for the hyperspace working set */ MM::Pte::MapPDE(MemoryLayout->HyperSpaceStart, MappingRange, &ValidPte); /* Set the hyperspace working set's PTE with the total PTE count */ MM::Paging::SetPte(MM::Paging::GetPteAddress((PVOID)MemoryLayout->HyperSpaceStart), MM_HYPERSPACE_PAGE_COUNT, 0); } /** * Maps a range of virtual addresses at the P5E (PML5) level. * * @param StartAddress * The beginning of the virtual address range to map. * * @param EndAddress * The end of the virtual address range to map. * * @param TemplateP5e * A template P5E to use for creating new entries. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pte::MapP5E(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMP5E TemplateP5e) { PMMP5E EndSpace, PointerP5e; /* Get P5E addresses */ PointerP5e = MM::Paging::GetP5eAddress(StartAddress); EndSpace = MM::Paging::GetP5eAddress(EndAddress); /* Iterate over all P5Es */ while(PointerP5e <= EndSpace) { /* Check if P5E is already mapped */ if(!MM::Paging::PteValid(PointerP5e)) { /* Map P5E */ MM::Paging::SetPte(TemplateP5e, MM::Pfn::AllocateBootstrapPages(1), 0); *PointerP5e = *TemplateP5e; /* Clear the page table */ RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(PointerP5e), MM_PAGE_SIZE); } /* Get next table entry */ PointerP5e = MM::Paging::GetNextPte(PointerP5e); } } /** * Maps a range of virtual addresses at the PPE (Page Directory Pointer Entry) level. * * @param StartAddress * The beginning of the virtual address range to map. * * @param EndAddress * The end of the virtual address range to map. * * @param TemplatePpe * A template PPE to use for creating new entries. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pte::MapPPE(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMPPE TemplatePpe) { PMMPPE EndSpace, PointerPpe; /* Get PPE addresses */ PointerPpe = MM::Paging::GetPpeAddress(StartAddress); EndSpace = MM::Paging::GetPpeAddress(EndAddress); /* Iterate over all PPEs */ while(PointerPpe <= EndSpace) { /* Check if PPE is already mapped */ if(!MM::Paging::PteValid(PointerPpe)) { /* Map PPE */ MM::Paging::SetPte(TemplatePpe, MM::Pfn::AllocateBootstrapPages(1), 0); *PointerPpe = *TemplatePpe; /* Clear the page table */ RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPpe), MM_PAGE_SIZE); } /* Get next table entry */ PointerPpe = MM::Paging::GetNextPte(PointerPpe); } } /** * Maps a range of virtual addresses at the PXE (PML4) level. * * @param StartAddress * The beginning of the virtual address range to map. * * @param EndAddress * The end of the virtual address range to map. * * @param TemplatePxe * A template PXE to use for creating new entries. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pte::MapPXE(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMPXE TemplatePxe) { PMMPXE EndSpace, PointerPxe; /* Get PXE addresses */ PointerPxe = MM::Paging::GetPxeAddress(StartAddress); EndSpace = MM::Paging::GetPxeAddress(EndAddress); /* Iterate over all PTEs */ while(PointerPxe <= EndSpace) { /* Check if PTE is already mapped */ if(!MM::Paging::PteValid(PointerPxe)) { /* Map PTE */ MM::Paging::SetPte(TemplatePxe, MM::Pfn::AllocateBootstrapPages(1), 0); *PointerPxe = *TemplatePxe; /* Clear the page table */ RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPxe), MM_PAGE_SIZE); } /* Get next table entry */ PointerPxe = MM::Paging::GetNextPte(PointerPxe); } } ================================================ FILE: xtoskrnl/mm/colors.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/colors.cc * DESCRIPTION: Memory manager page coloring subsystem * DEVELOPERS: Aiken Harris */ #include /** * Computes & initializes the system's page coloring. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Colors::ComputePageColoring(VOID) { UNIMPLEMENTED; /* Compute L2 paging colors and mask */ PagingColors = MM_PAGING_COLORS; PagingColorsMask = PagingColors - 1; } /** * Retrieves a pointer to the color table for a specific page list and color. * * @param PageList * The page list type (e.g., FreePageList, ZeroedPageList). * * @param Color * Supplies the specific color index. * * @return This routine returns a pointer to the corresponding MMCOLOR_TABLES structure. * * @since XT 1.0 */ XTAPI PMMCOLOR_TABLES MM::Colors::GetFreePages(IN MMPAGELISTS PageList, IN ULONG Color) { /* Return a pointer to the requested color table entry */ return &FreePages[PageList][Color]; } /** * Retrieves a pointer to the modified pages list for a specific color. * * @param Color * Supplies the specific color index. * * @return This routine returns a pointer to the corresponding MMPFNLIST structure. * * @since XT 1.0 */ XTAPI PMMPFNLIST MM::Colors::GetModifiedPages(IN ULONG Color) { return &ModifiedPages[Color]; } /** * Retrieves the next available color for page coloring. * * @return This routine returns the next color value, ensuring it stays within the valid color range. * * @since XT 1.0 */ XTAPI ULONG MM::Colors::GetNextColor(VOID) { /* Increment the color counter and wrap it around using the mask */ return ((++PagingColors) & PagingColorsMask); } /** * Retrieves the total number of page colors configured in the system. * * @return This routine returns the number of page colors. * * @since XT 1.0 */ XTAPI ULONG MM::Colors::GetPagingColors(VOID) { /* Return the total number of page colors */ return PagingColors; } /** * Retrieves the bitmask used for calculating a page's color. * * @return This routine returns the page color mask. * * @since XT 1.0 */ XTAPI ULONG MM::Colors::GetPagingColorsMask(VOID) { /* Return the mask used for page coloring calculations */ return PagingColorsMask; } /** * Initializes the data structures for page coloring. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Colors::InitializeColorTables(VOID) { PMMMEMORY_LAYOUT MemoryLayout; PMMPTE PointerPte, LastPte; ULONG Color; PMMPTE ValidPte; /* Get the memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Set the base address of the color tables to start right after the PFN database */ FreePages[0] = (PMMCOLOR_TABLES)&((PMMPFN)MemoryLayout->PfnDatabase)[MM::Pfn::GetHighestPhysicalPage() + 1]; /* Calculate the virtual address range for both color tables */ PointerPte = MM::Paging::GetPteAddress(&FreePages[0][0]); LastPte = MM::Paging::GetPteAddress((PVOID)((ULONG_PTR)FreePages[0] + (2 * PagingColors * sizeof(MMCOLOR_TABLES)) - 1)); /* Get a pointer to a PTE template */ ValidPte = MM::Pte::GetValidPte(); /* Ensure the entire virtual address range for the color tables is mapped */ while(PointerPte <= LastPte) { /* Check if a page in the range is not mapped */ if(!MM::Paging::PteValid(PointerPte)) { /* Use the bootstrap allocator to get a physical page */ MM::Paging::SetPte(ValidPte, MM::Pfn::AllocateBootstrapPages(1), 0); *PointerPte = *ValidPte; /* Zero out the newly mapped page */ RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPte), MM_PAGE_SIZE); } /* Move to the next PTE in the range */ PointerPte = MM::Paging::GetNextPte(PointerPte); } /* Set the pointer for the second list */ FreePages[1] = &FreePages[0][PagingColors]; /* Initialize all entries in both color tables */ for(Color = 0; Color < PagingColors; Color++) { /* Initialize the FreePageList entry for the current color */ FreePages[FreePageList][Color].Flink = MAXULONG_PTR; FreePages[FreePageList][Color].Blink = (PVOID)MAXULONG_PTR; FreePages[FreePageList][Color].Count = 0; /* Initialize the ZeroedPageList entry for the current color */ FreePages[ZeroedPageList][Color].Flink = MAXULONG_PTR; FreePages[ZeroedPageList][Color].Blink = (PVOID)MAXULONG_PTR; FreePages[ZeroedPageList][Color].Count = 0; } } ================================================ FILE: xtoskrnl/mm/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/data.cc * DESCRIPTION: Memory Manager global and static data * DEVELOPERS: Aiken Harris */ #include /* Expansion table used to track pool memory allocations */ PPOOL_TRACKING_TABLE MM::Allocator::AllocationsTrackingExpansionTable; /* Total number of entries in the expansion allocations tracking table */ SIZE_T MM::Allocator::AllocationsTrackingExpansionTableSize; /* Global table used to track pool memory allocations */ PPOOL_TRACKING_TABLE MM::Allocator::AllocationsTrackingTable; /* Spinlock protecting the allocations table */ KSPIN_LOCK MM::Allocator::AllocationsTrackingTableLock; /* Bitmask used during the hashing process */ SIZE_T MM::Allocator::AllocationsTrackingTableMask; /* Total number of entries in the global allocations tracking table */ SIZE_T MM::Allocator::AllocationsTrackingTableSize; /* Active number of big allocations to trigger table expansion */ ULONG MM::Allocator::BigAllocationsInUse; /* Pointer to the hash table for tracking page-aligned memory */ PPOOL_TRACKING_BIG_ALLOCATIONS MM::Allocator::BigAllocationsTrackingTable; /* Bitmask used for fast modulo arithmetic during hash bucket lookups */ SIZE_T MM::Allocator::BigAllocationsTrackingTableHash; /* Spinlock protecting the big allocations table */ KSPIN_LOCK MM::Allocator::BigAllocationsTrackingTableLock; /* Maximum capacity of the tracking hash table */ SIZE_T MM::Allocator::BigAllocationsTrackingTableSize; /* Array of CPU-local tracking tables */ PPOOL_TRACKING_TABLE MM::Allocator::TagTables[MM_POOL_TRACKING_TABLES]; /* Array of free page lists segregated by cache color */ PMMCOLOR_TABLES MM::Colors::FreePages[FreePageList + 1]; /* Array of modified pages segregated by cache color */ MMPFNLIST MM::Colors::ModifiedPages[MM_PAGING_COLORS] = {{0, ModifiedPageList, MAXULONG_PTR, MAXULONG_PTR}}; /* Number of supported page colors */ ULONG MM::Colors::PagingColors; /* Bitmask used to calculate the cache color index */ ULONG MM::Colors::PagingColorsMask; /* Allocation descriptors dedicated for hardware layer */ LOADER_MEMORY_DESCRIPTOR MM::HardwarePool::HardwareAllocationDescriptors[MM_HARDWARE_ALLOCATION_DESCRIPTORS]; /* Live address of kernel's hardware heap */ PVOID MM::HardwarePool::HardwareHeapStart = MM_HARDWARE_HEAP_START_ADDRESS; /* Number of used hardware allocation descriptors */ ULONG MM::HardwarePool::UsedHardwareAllocationDescriptors = 0; /* Global structure describing the virtual memory layout of the system */ MMMEMORY_LAYOUT MM::Manager::MemoryLayout; /* Total number of PTEs reserved for system space mapping */ PFN_NUMBER MM::Manager::NumberOfSystemPtes; /* Physical memory block descriptor */ PPHYSICAL_MEMORY_DESCRIPTOR MM::Manager::PhysicalMemoryBlock; /* Instance of the page map routines for the current PML level */ MM::PPAGEMAP MM::Paging::PmlRoutines; /* Total number of physical pages available for allocation */ PFN_NUMBER MM::Pfn::AvailablePages; /* Head of the list containing physical pages marked as defective */ MMPFNLIST MM::Pfn::BadPagesList = {0, BadPageList, MAXULONG_PTR, MAXULONG_PTR}; /* Biggest free memory descriptor */ PLOADER_MEMORY_DESCRIPTOR MM::Pfn::FreeDescriptor; /* List containing free physical pages */ MMPFNLIST MM::Pfn::FreePagesList = {0, FreePageList, MAXULONG_PTR, MAXULONG_PTR}; /* Highest physical page number */ ULONG_PTR MM::Pfn::HighestPhysicalPage; /* Lowest physical page number */ ULONG_PTR MM::Pfn::LowestPhysicalPage; /* List containing modified pages */ MMPFNLIST MM::Pfn::ModifiedPagesList = {0, ModifiedPageList, MAXULONG_PTR, MAXULONG_PTR}; /* List containing modified pages mapped as read-only */ MMPFNLIST MM::Pfn::ModifiedReadOnlyPagesList = {0, ModifiedReadOnlyPageList, MAXULONG_PTR, MAXULONG_PTR}; /* Number of physical pages */ ULONGLONG MM::Pfn::NumberOfPhysicalPages; /* Old biggest free memory descriptor */ LOADER_MEMORY_DESCRIPTOR MM::Pfn::OriginalFreeDescriptor; /* Array of pointers to PFN lists */ PMMPFNLIST MM::Pfn::PageLocationList[] = {&ZeroedPagesList, &FreePagesList, &StandbyPagesList, &ModifiedPagesList, &ModifiedReadOnlyPagesList, &BadPagesList, NULLPTR, NULLPTR}; /* Bitmap used to track physical pages */ RTL_BITMAP MM::Pfn::PfnBitMap; /* List containing pages mapped as Read-Only (ROM) */ MMPFNLIST MM::Pfn::RomPagesList = {0, StandbyPageList, MAXULONG_PTR, MAXULONG_PTR}; /* List containing standby pages (clean, can be reclaimed or repurposed) */ MMPFNLIST MM::Pfn::StandbyPagesList = {0, StandbyPageList, MAXULONG_PTR, MAXULONG_PTR}; /* List containing free physical pages that have been zeroed out */ MMPFNLIST MM::Pfn::ZeroedPagesList = {0, ZeroedPageList, MAXULONG_PTR, MAXULONG_PTR}; /* Non-paged pool descriptor */ POOL_DESCRIPTOR MM::Pool::NonPagedPoolDescriptor; /* PFN marking the initial non-paged pool end boundary */ PFN_NUMBER MM::Pool::NonPagedPoolFrameEnd; /* PFN marking the initial non-paged pool start boundary */ PFN_NUMBER MM::Pool::NonPagedPoolFrameStart; /* Array of non-paged pool free list heads */ LIST_ENTRY MM::Pool::NonPagedPoolFreeList[MM_MAX_FREE_PAGE_LIST_HEADS]; /* Random cookie used to obfuscate pool links */ ULONG MM::Pool::PoolSecureCookie; /* Array of pool descriptors */ PPOOL_DESCRIPTOR MM::Pool::PoolVector[2]; /* Array of lists for available System PTEs, separated by pool type */ MMPTE MM::Pte::FirstSystemFreePte[MaximumPtePoolTypes]; /* Virtual base address of the System PTE space */ PMMPTE MM::Pte::SystemPteBase; /* End addresses for the System PTE ranges */ PMMPTE MM::Pte::SystemPtesEnd[MaximumPtePoolTypes]; /* Start addresses for the System PTE ranges */ PMMPTE MM::Pte::SystemPtesStart[MaximumPtePoolTypes]; /* Total count of available System PTEs */ PFN_COUNT MM::Pte::TotalSystemFreePtes[MaximumPtePoolTypes]; /* Template PTE entry containing standard flags for a valid, present kernel page */ MMPTE MM::Pte::ValidPte; ================================================ FILE: xtoskrnl/mm/exports.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/exports.cc * DESCRIPTION: C-compatible API wrappers for exported kernel functions * DEVELOPERS: Aiken Harris */ #include /** * Allocates a block of memory from the specified pool type. * * @param PoolType * Specifies the type of pool to allocate from. * * @param Bytes * Specifies the number of bytes to allocate. * * @param Memory * Supplies a pointer to the allocated memory. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MmAllocatePool(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, OUT PVOID *Memory) { return MM::Allocator::AllocatePool(PoolType, Bytes, Memory); } /** * Allocates a block of memory from the specified pool type. * * @param PoolType * Specifies the type of pool to allocate from. * * @param Bytes * Specifies the number of bytes to allocate. * * @param Memory * Supplies a pointer to the allocated memory. * * @param Tag * Specifies the allocation identifying tag. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MmAllocatePoolWithTag(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, OUT PVOID *Memory, IN ULONG Tag) { return MM::Allocator::AllocatePool(PoolType, Bytes, Memory, Tag); } /** * Frees a previously allocated memory pool. * * @param VirtualAddress * Supplies the base virtual address of the pool allocation to free. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MmFreePool(IN PVOID VirtualAddress) { return MM::Allocator::FreePool(VirtualAddress); } /** * Frees a previously allocated memory pool. * * @param VirtualAddress * Supplies the base virtual address of the pool allocation to free. * * @param Tag * Specifies the allocation identifying tag. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MmFreePoolWithTag(IN PVOID VirtualAddress, IN ULONG Tag) { return MM::Allocator::FreePool(VirtualAddress, Tag); } ================================================ FILE: xtoskrnl/mm/hlpool.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/hlpool.cc * DESCRIPTION: Hardware layer pool memory management * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Allocates physical memory for kernel hardware layer before memory manager gets initialized. * * @param PageCount * Supplies the number of pages to be allocated. * * @param Aligned * Specifies whether allocated memory should be aligned to 64k boundary or not. * * @param MaximumAddress * Supplies the maximum acceptable physical address for the allocation. * * @param Buffer * Supplies a buffer that receives the physical address. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::HardwarePool::AllocateHardwareMemory(IN PFN_NUMBER PageCount, IN BOOLEAN Aligned, IN ULONGLONG MaximumAddress, OUT PPHYSICAL_ADDRESS Buffer) { PLOADER_MEMORY_DESCRIPTOR Descriptor, ExtraDescriptor, HardwareDescriptor; PLIST_ENTRY ListEntry, LoaderMemoryDescriptors; PFN_NUMBER Alignment, MaxPage; ULONGLONG PhysicalAddress; /* Assume failure */ (*Buffer).QuadPart = 0; /* Calculate maximum page address based on the requested limit */ MaxPage = MaximumAddress >> MM_PAGE_SHIFT; /* Make sure there are at least 2 descriptors available */ if((UsedHardwareAllocationDescriptors + 2) > MM_HARDWARE_ALLOCATION_DESCRIPTORS) { /* Not enough descriptors, return error */ return STATUS_INSUFFICIENT_RESOURCES; } /* Get a list of memory descriptors provided by the boot loader */ LoaderMemoryDescriptors = KE::BootInformation::GetMemoryDescriptors(); /* Scan memory descriptors provided by the boot loader */ ListEntry = LoaderMemoryDescriptors->Blink; while(ListEntry != LoaderMemoryDescriptors) { Descriptor = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_DESCRIPTOR, ListEntry); /* Align memory to 64KB if needed */ Alignment = Aligned ? (((Descriptor->BasePage + 0x0F) & ~0x0F) - Descriptor->BasePage) : 0; /* Ensure that memory type is free for this descriptor */ if(Descriptor->MemoryType == LoaderFree) { /* Check if descriptor is big enough and if it fits under the maximum physical address */ if(Descriptor->BasePage && ((Descriptor->BasePage + PageCount + Alignment) < MaxPage) && (Descriptor->PageCount >= (PageCount + Alignment))) { /* Set physical address */ PhysicalAddress = (Descriptor->BasePage + Alignment) << MM_PAGE_SHIFT; break; } } /* Move to previous descriptor */ ListEntry = ListEntry->Blink; } /* Make sure we found a descriptor */ if(ListEntry == LoaderMemoryDescriptors) { /* Descriptor not found, return error */ return STATUS_INSUFFICIENT_RESOURCES; } /* Allocate new descriptor */ HardwareDescriptor = &HardwareAllocationDescriptors[UsedHardwareAllocationDescriptors]; HardwareDescriptor->BasePage = Descriptor->BasePage + Alignment; HardwareDescriptor->MemoryType = LoaderHardwareCachedMemory; HardwareDescriptor->PageCount = PageCount; /* Update hardware allocation descriptors count */ UsedHardwareAllocationDescriptors++; /* Check if alignment was done */ if(Alignment) { /* Check if extra descriptor is needed to describe the allocation */ if(Descriptor->PageCount > (PageCount + Alignment)) { /* Initialize extra descriptor */ ExtraDescriptor = &HardwareAllocationDescriptors[UsedHardwareAllocationDescriptors]; ExtraDescriptor->BasePage = Descriptor->BasePage + Alignment + (ULONG)PageCount; ExtraDescriptor->MemoryType = LoaderFree; ExtraDescriptor->PageCount = Descriptor->PageCount - (Alignment + (ULONG)PageCount); /* Update hardware allocation descriptors count */ UsedHardwareAllocationDescriptors++; /* Insert extra descriptor in the list */ RTL::LinkedList::InsertHeadList(&Descriptor->ListEntry, &ExtraDescriptor->ListEntry); } /* Trim source descriptor to the alignment */ Descriptor->PageCount = Alignment; /* Insert new descriptor in the list */ RTL::LinkedList::InsertHeadList(&Descriptor->ListEntry, &HardwareDescriptor->ListEntry); } else { /* Consume pages from the source descriptor */ Descriptor->BasePage += (ULONG)PageCount; Descriptor->PageCount -= (ULONG)PageCount; /* Insert new descriptor in the list */ RTL::LinkedList::InsertTailList(&Descriptor->ListEntry, &HardwareDescriptor->ListEntry); /* Check if source descriptor is fully consumed */ if(Descriptor->PageCount == 0) { /* Remove descriptor from the list */ RTL::LinkedList::RemoveEntryList(&Descriptor->ListEntry); } } /* Return physical address */ (*Buffer).QuadPart = PhysicalAddress; return STATUS_SUCCESS; } /** * Allocates a physical page in low memory (addressable in real-mode) and maps it into the virtual address space. * * @param MemoryAddress * Supplies a pointer to a variable that receives the identity-mapped virtual address of the allocated memory. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::HardwarePool::AllocateRealModeMemory(IN PFN_NUMBER PageCount, OUT PVOID *MemoryAddress) { PHYSICAL_ADDRESS PhysicalAddress; PFN_NUMBER PageFrameNumber; PVOID VirtualAddress; XTSTATUS Status; /* Allocate physical memory in first 1MB */ Status = AllocateHardwareMemory(PageCount, TRUE, 0x100000, &PhysicalAddress); if(Status != STATUS_SUCCESS) { /* Failed to allocate memory, return error */ return Status; } /* Calculate virtual address and page frame number */ VirtualAddress = (PVOID)(ULONG_PTR)PhysicalAddress.QuadPart; PageFrameNumber = PhysicalAddress.QuadPart >> MM_PAGE_SHIFT; /* Identity map the memory to the virtual address */ Status = MM::Paging::MapVirtualAddress(VirtualAddress, PageFrameNumber, MM_PTE_EXECUTE_READWRITE); if(Status != STATUS_SUCCESS) { /* Failed to map memory, return error */ return Status; } /* Set the trampoline virtual address and return success */ *MemoryAddress = VirtualAddress; return STATUS_SUCCESS; } /** * Maps physical address to the virtual memory area used by kernel hardware layer. * * @param PhysicalAddress * Supplies the physical address to map. * * @param PageCount * Supplies the number of pages to be mapped. * * @param FlushTlb * Specifies whether to flush the TLB or not. * * @param VirtualAddress * Supplies a buffer that receives the virtual address of the mapped pages. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::HardwarePool::MapHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress, IN PFN_NUMBER PageCount, IN BOOLEAN FlushTlb, OUT PVOID *VirtualAddress) { PVOID BaseAddress, ReturnAddress; PFN_NUMBER MappedPages; PMMPTE PtePointer; /* Initialize variables */ BaseAddress = HardwareHeapStart; MappedPages = 0; ReturnAddress = BaseAddress; *VirtualAddress = NULLPTR; /* Iterate through all pages */ while(MappedPages < PageCount) { /* Check if address overflows */ if(BaseAddress == NULLPTR) { /* Not enough free pages, return error */ return STATUS_INSUFFICIENT_RESOURCES; } /* Get PTE pointer and advance to next page */ PtePointer = MM::Paging::GetPteAddress(ReturnAddress); ReturnAddress = (PVOID)((ULONG_PTR)ReturnAddress + MM_PAGE_SIZE); /* Check if PTE is valid */ if(MM::Paging::PteValid(PtePointer)) { /* PTE is not available, go to the next one */ BaseAddress = ReturnAddress; MappedPages = 0; continue; } /* Increase number of mapped pages */ MappedPages++; } /* Take the actual base address with an offset */ ReturnAddress = (PVOID)((ULONG_PTR)BaseAddress + PAGE_OFFSET(PhysicalAddress.LowPart)); /* Check if base address starts at the beginning of the heap */ if(BaseAddress == HardwareHeapStart) { /* Move heap beyond base address */ HardwareHeapStart = (PVOID)((ULONG_PTR)BaseAddress + ((ULONG_PTR)PageCount << MM_PAGE_SHIFT)); } /* Iterate through mapped pages */ while(MappedPages--) { /* Get PTE pointer */ PtePointer = MM::Paging::GetPteAddress(BaseAddress); /* Fill the PTE */ MM::Paging::SetPte(PtePointer, (PFN_NUMBER)(PhysicalAddress.QuadPart >> MM_PAGE_SHIFT), MM_PTE_READWRITE); /* Advance to the next address */ PhysicalAddress.QuadPart += MM_PAGE_SIZE; BaseAddress = (PVOID)((ULONG_PTR)BaseAddress + MM_PAGE_SIZE); } /* Check if TLB needs to be flushed */ if(FlushTlb) { /* Flush the TLB */ MM::Paging::FlushTlb(); } /* Return virtual address */ *VirtualAddress = ReturnAddress; return STATUS_SUCCESS; } /** * Marks existing mapping as CD/WT to avoid delays in write-back cache. * * @param VirtualAddress * Supplies the virtual address region to mark as CD/WT. * * @param PageCount * Supplies the number of mapped pages. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::HardwarePool::MarkHardwareMemoryWriteThrough(IN PVOID VirtualAddress, IN PFN_NUMBER PageCount) { PMMPTE PtePointer; PFN_NUMBER Page; /* Get PTE address from virtual address */ PtePointer = MM::Paging::GetPteAddress(VirtualAddress); /* Iterate through mapped pages */ for(Page = 0; Page < PageCount; Page++) { /* Mark pages as CD/WT */ MM::Paging::SetPteCaching(PtePointer, TRUE, TRUE); MM::Paging::GetNextEntry(PtePointer); } } /** * Remaps the PTE to new physical address. * * @param VirtualAddress * Supplies the virtual address to remap. * * @param PhysicalAddress * Supplies a new physical address. * * @param FlushTlb * Specifies whether to flush the TLB or not. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::HardwarePool::RemapHardwareMemory(IN PVOID VirtualAddress, IN PHYSICAL_ADDRESS PhysicalAddress, IN BOOLEAN FlushTlb) { PMMPTE PtePointer; /* Get PTE address from virtual address */ PtePointer = MM::Paging::GetPteAddress(VirtualAddress); /* Remap the PTE */ MM::Paging::SetPte(PtePointer, (PFN_NUMBER)(PhysicalAddress.QuadPart >> MM_PAGE_SHIFT), MM_PTE_READWRITE); /* Check if TLB needs to be flushed */ if(FlushTlb) { /* Flush the TLB */ MM::Paging::FlushTlb(); } } /** * Unmaps a Page Table Entry corresponding to the given virtual address. * * @param VirtualAddress * Supplies the virtual address to unmap. * * @param PageCount * Supplies the number of mapped pages. * * @param FlushTlb * Specifies whether to flush the TLB or not. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::HardwarePool::UnmapHardwareMemory(IN PVOID VirtualAddress, IN PFN_NUMBER PageCount, IN BOOLEAN FlushTlb) { PMMPTE PtePointer; PFN_NUMBER Page; /* Check if address is valid hardware memory */ if(VirtualAddress < (PVOID)MM_HARDWARE_VA_START) { /* Invalid address, return error */ return STATUS_INVALID_PARAMETER; } /* Align virtual address down to page boundary */ VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress & ~(MM_PAGE_SIZE - 1)); /* Get PTE address from virtual address */ PtePointer = MM::Paging::GetPteAddress(VirtualAddress); /* Iterate through mapped pages */ for(Page = 0; Page < PageCount; Page++) { /* Unmap the PTE and get the next one */ MM::Paging::ClearPte(PtePointer); PtePointer++; } /* Check if TLB needs to be flushed */ if(FlushTlb) { /* Flush the TLB */ MM::Paging::FlushTlb(); } /* Check if heap can be reused */ if(HardwareHeapStart > VirtualAddress) { /* Free VA space */ HardwareHeapStart = VirtualAddress; } /* Return success */ return STATUS_SUCCESS; } ================================================ FILE: xtoskrnl/mm/i686/mmgr.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/i686/mmgr.cc * DESCRIPTION: Memory Manager * DEVELOPERS: Aiken Harris */ #include /** * Calculates the maximum possible size of the non-paged pool. * * @param PoolSize * A pointer to a variable that will receive the number of pages available for the non-paged pool. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::ComputeMaximumNonPagedPoolSize(OUT PPFN_NUMBER PoolSize) { ULONG_PTR MaximumNonPagedPoolSize; ULONGLONG PhysicalPages; /* Get number of physical pages */ PhysicalPages = MM::Pfn::GetNumberOfPhysicalPages(); /* Start with 1MiB and reserve space for PFN database */ MaximumNonPagedPoolSize = 1048576; /* Check if system has at least 512MiB of physical memory */ if(PhysicalPages >= 126976) { /* Add 200KiB for each MiB above 4MiB */ MaximumNonPagedPoolSize += ((PhysicalPages - 1024)/256) * 204800; /* Check if non-paged pool has at least 128MiB */ if(MaximumNonPagedPoolSize < 134217728) { /* Expand non-paged pool size to 128MiB */ MaximumNonPagedPoolSize = 134217728; } } else { /* Add 400KiB for each MiB above 4MiB */ MaximumNonPagedPoolSize += ((PhysicalPages - 1024)/256) * 409600; } /* Check if non-paged pool does not exceed 256MiB */ if(MaximumNonPagedPoolSize > 268435456) { /* Limit non-paged pool size to 256MiB */ MaximumNonPagedPoolSize = 268435456; } /* Return maximum non-paged pool size in pages */ *PoolSize = SIZE_TO_PAGES(MaximumNonPagedPoolSize); } /** * Calculates the size of the non-paged pool. * * @param PoolSize * A pointer to a variable that will receive the number of pages available for the non-paged pool. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::ComputeNonPagedPoolSize(OUT PPFN_NUMBER PoolSize) { ULONG_PTR NonPagedPoolSize; ULONGLONG PhysicalPages; /* Get number of physical pages */ PhysicalPages = MM::Pfn::GetNumberOfPhysicalPages(); /* Verify if system has less than 256MiB of physical memory */ if(PhysicalPages <= 65536) { /* Reduce initial non-paged pool size to 2MiB to save memory */ NonPagedPoolSize = 2097152; } else { /* Start with 256KiB and add 32KiB for each MiB above 4MiB */ NonPagedPoolSize = 262144 + (((PhysicalPages - 1024) / 256) * 32768); if(NonPagedPoolSize > 134217728) { /* Limit non-paged pool size to 128MiB */ NonPagedPoolSize = 134217728; } } /* Return non-paged pool size in pages, aligned down to page size boundary */ *PoolSize = SIZE_TO_PAGES(ROUND_DOWN(NonPagedPoolSize, MM_PAGE_SIZE)); } /** * Calculates the size of the paged pool. * * @param PoolSize * A pointer to a variable that will receive the number of pages available for the paged pool. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::ComputePagedPoolSize(OUT PPFN_NUMBER PoolSize) { ULONG_PTR PagedPoolSize, PteCount; ULONG PtesPerPage; /* Start with maximum non-paged pool size */ ComputeMaximumNonPagedPoolSize(&PagedPoolSize); PagedPoolSize *= MM_PAGE_SIZE; /* Check XPA status */ if(MM::Paging::GetXpaStatus()) { /* Four times the non-paged pool size on PAE-enabled systems */ PagedPoolSize *= 4; } else { /* Double the non-paged pool size on PAE-disabled systems */ PagedPoolSize *= 2; } /* Check if paged pool does not overlap non-paged pool */ if(PagedPoolSize > (ULONG_PTR)MemoryLayout.NonPagedSystemPoolStart - (ULONG_PTR)MemoryLayout.PagedPoolStart) { /* Limit paged pool size to maximum possible */ PagedPoolSize = (ULONG_PTR)MemoryLayout.NonPagedSystemPoolStart - (ULONG_PTR)MemoryLayout.PagedPoolStart; } /* Ensure that paged pool size is at least 32MiB */ if(PagedPoolSize < 33554432) { /* Increase paged pool size to at least 32MiB */ PagedPoolSize = 33554432; } /* Get the number of PTEs per page and calculate size of paged pool */ PtesPerPage = MM::Pte::GetPtesPerPage(); PteCount = ((SIZE_TO_PAGES(PagedPoolSize) + (PtesPerPage - 1)) / PtesPerPage); /* Return paged pool size */ *PoolSize = (PFN_NUMBER)(PteCount * PtesPerPage); } /** * Calculates the size of the session space. * * @param SpaceSize * A pointer to a variable that will receive the number of pages available by the session space. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::ComputeSessionSpaceSize(OUT PPFN_NUMBER SpaceSize) { PFN_NUMBER SessionSpaceSize; /* Session Pool, Session View, Session Image, Session Working Set and System View takes 108MiB */ SessionSpaceSize = 113246208; /* Return number of pages used by the session space */ *SpaceSize = SessionSpaceSize / MM_PAGE_SIZE; } /** * Calculates the size of the system PTEs. * * @param PteSize * A pointer to a variable that will receive the number of system PTEs. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::ComputeSystemPteSize(OUT PPFN_NUMBER PteSize) { PFN_NUMBER SystemPteSize; /* Check if system has less than 19MiB of physical memory */ if(MM::Pfn::GetNumberOfPhysicalPages() < 4864) { /* Set minimal system PTE size */ SystemPteSize = 7000; } else { /* Use standard system PTE size */ SystemPteSize = 11000; /* Check if system has more than 32MiB of physical memory */ if(MM::Pfn::GetNumberOfPhysicalPages() > 8192) { /* Double system PTE size */ SystemPteSize *= 2; /* Check if system has more than 256MiB of physical memory */ if(MM::Pfn::GetNumberOfPhysicalPages() > 65536) { /* Double system PTE size */ SystemPteSize *= 2; } } } /* Return system PTE size */ *PteSize = SystemPteSize; } /** * Dumps the kernel's memory layout. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::DumpMemoryLayout(VOID) { /* Dump memory layout */ DebugPrint(L"System with %zu MiB of installed memory:\n" L"User Space: %.8P - %.8P\n" L"Loader Mappings: %.8P - %.8P\n" L"PFN Database: %.8P - %.8P\n" L"Non-Paged Pool: %.8P - %.8P\n" L"Session Space: %.8P - %.8P\n" L"PTE Space: %.8P - %.8P\n" L"Hyper Space: %.8P - %.8P\n" L"System Working Set: %.8P - %.8P\n" L"System Cache: %.8P - %.8P\n" L"Paged Pool: %.8P - %.8P\n" L"Non-Paged System Pool: %.8P - %.8P\n" L"Non-Paged Expansion Pool: %.8P - %.8P\n" L"Shared System Page: %.8P - %.8P\n" L"Hardware Pool: %.8P - %.8P\n", GetInstalledMemorySize(), MemoryLayout.UserSpaceStart, MemoryLayout.UserSpaceEnd, MemoryLayout.LoaderMappingsStart, MemoryLayout.LoaderMappingsEnd, MemoryLayout.PfnDatabase, (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + (ULONG_PTR)MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE), MemoryLayout.NonPagedPoolStart, MemoryLayout.NonPagedPoolEnd, MemoryLayout.SessionSpaceStart, MemoryLayout.SessionSpaceEnd, MemoryLayout.PteSpaceStart, MemoryLayout.PteSpaceEnd, MemoryLayout.HyperSpaceStart, MemoryLayout.HyperSpaceEnd, MemoryLayout.SystemWorkingSetStart, MemoryLayout.SystemWorkingSetEnd, MemoryLayout.SystemCacheStart, MemoryLayout.SystemCacheEnd, MemoryLayout.PagedPoolStart, MemoryLayout.PagedPoolEnd, MemoryLayout.NonPagedSystemPoolStart, MemoryLayout.NonPagedSystemPoolEnd, MemoryLayout.NonPagedExpansionPoolStart, MemoryLayout.NonPagedExpansionPoolEnd, MemoryLayout.SharedSystemPageStart, MemoryLayout.SharedSystemPageEnd, MemoryLayout.HardwarePoolStart, MemoryLayout.HardwarePoolEnd); } /** * Initializes the kernel's virtual memory layout. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::InitializeMemoryLayout(VOID) { PFN_NUMBER MaximumNonPagedPoolSize; ULONG_PTR PfnDatabaseEnd; /* Check if 3-level paging (PAE) is enabled */ if(MM::Paging::GetXpaStatus()) { /* Set PML3 base address */ MemoryLayout.SelfMapAddress = (PVOID)MM_PTE_BASE; /* Define memory layout for 3-level paging */ MemoryLayout.NonCanonicalStart = (PVOID)0x00000000; MemoryLayout.NonCanonicalEnd = (PVOID)0x00000000; MemoryLayout.ReservedSystemPoolStart = (PVOID)0x00000000; MemoryLayout.ReservedSystemPoolEnd = (PVOID)0x00000000; MemoryLayout.UserSpaceStart = (PVOID)0x00010000; MemoryLayout.UserSpaceEnd = (PVOID)0x7FFEFFFF; MemoryLayout.LoaderMappingsStart = (PVOID)0x80000000; MemoryLayout.LoaderMappingsEnd = (PVOID)0x90000000; MemoryLayout.NonPagedPoolStart = (PVOID)0x90000000; MemoryLayout.NonPagedPoolEnd = (PVOID)0xB0000000; MemoryLayout.SessionSpaceStart = (PVOID)0xB0000000; MemoryLayout.SessionSpaceEnd = (PVOID)0xC0000000; MemoryLayout.PteSpaceStart = (PVOID)0xC0000000; MemoryLayout.PteSpaceEnd = (PVOID)0xC07FFFFF; MemoryLayout.HyperSpaceStart = (PVOID)0xC0800000; MemoryLayout.HyperSpaceEnd = (PVOID)0xC0BFFFFF; MemoryLayout.SystemWorkingSetStart = (PVOID)0xC0C00000; MemoryLayout.SystemWorkingSetEnd = (PVOID)0xC0FFFFFF; MemoryLayout.SystemCacheStart = (PVOID)0xC1000000; MemoryLayout.SystemCacheEnd = (PVOID)0xE0FFFFFF; MemoryLayout.PagedPoolStart = (PVOID)0xE1000000; MemoryLayout.PagedPoolEnd = (PVOID)0xECC00000; MemoryLayout.NonPagedSystemPoolStart = (PVOID)0xECC00000; MemoryLayout.NonPagedSystemPoolEnd = (PVOID)0xF7BE0000; MemoryLayout.NonPagedExpansionPoolStart = (PVOID)0xF7BE0000; MemoryLayout.NonPagedExpansionPoolEnd = (PVOID)0xFFBFF000; MemoryLayout.SharedSystemPageStart = (PVOID)0xFFBFF000; MemoryLayout.SharedSystemPageEnd = (PVOID)0xFFC00000; MemoryLayout.HardwarePoolStart = (PVOID)0xFFC00000; MemoryLayout.HardwarePoolEnd = (PVOID)0xFFFFFFFF; } else { /* Set PML2 base address */ MemoryLayout.SelfMapAddress = (PVOID)MM_PTE_BASE; /* Define memory layout for 2-level paging */ MemoryLayout.NonCanonicalStart = (PVOID)0x00000000; MemoryLayout.NonCanonicalEnd = (PVOID)0x00000000; MemoryLayout.ReservedSystemPoolStart = (PVOID)0x00000000; MemoryLayout.ReservedSystemPoolEnd = (PVOID)0x00000000; MemoryLayout.UserSpaceStart = (PVOID)0x00010000; MemoryLayout.UserSpaceEnd = (PVOID)0x7FFEFFFF; MemoryLayout.LoaderMappingsStart = (PVOID)0x80000000; MemoryLayout.LoaderMappingsEnd = (PVOID)0x90000000; MemoryLayout.NonPagedPoolStart = (PVOID)0x90000000; MemoryLayout.NonPagedPoolEnd = (PVOID)0xB0000000; MemoryLayout.SessionSpaceStart = (PVOID)0xB0000000; MemoryLayout.SessionSpaceEnd = (PVOID)0xC0000000; MemoryLayout.PteSpaceStart = (PVOID)0xC0000000; MemoryLayout.PteSpaceEnd = (PVOID)0xC03FFFFF; MemoryLayout.HyperSpaceStart = (PVOID)0xC0400000; MemoryLayout.HyperSpaceEnd = (PVOID)0xC07FFFFF; MemoryLayout.SystemWorkingSetStart = (PVOID)0xC0C00000; MemoryLayout.SystemWorkingSetEnd = (PVOID)0xC0FFFFFF; MemoryLayout.SystemCacheStart = (PVOID)0xC1000000; MemoryLayout.SystemCacheEnd = (PVOID)0xE0FFFFFF; MemoryLayout.PagedPoolStart = (PVOID)0xE1000000; MemoryLayout.PagedPoolEnd = (PVOID)0xECC00000; MemoryLayout.NonPagedSystemPoolStart = (PVOID)0xECC00000; MemoryLayout.NonPagedSystemPoolEnd = (PVOID)0xF7BE0000; MemoryLayout.NonPagedExpansionPoolStart = (PVOID)0xF7BE0000; MemoryLayout.NonPagedExpansionPoolEnd = (PVOID)0xFFBFF000; MemoryLayout.SharedSystemPageStart = (PVOID)0xFFBFF000; MemoryLayout.SharedSystemPageEnd = (PVOID)0xFFC00000; MemoryLayout.HardwarePoolStart = (PVOID)0xFFC00000; MemoryLayout.HardwarePoolEnd = (PVOID)0xFFFFFFFF; } /* Compute allocation size for the PFN database */ MM::Pfn::ComputePfnDatabaseSize(&MemoryLayout.PfnDatabaseSize); /* Compute boot image size */ ComputeBootImageSize(&MemoryLayout.LoaderMappingsSize); /* Compute session space size */ ComputeSessionSpaceSize(&MemoryLayout.SessionSpaceSize); /* Update loader mappings space end address */ MemoryLayout.LoaderMappingsEnd = (PVOID)((ULONG_PTR)MemoryLayout.LoaderMappingsStart + MemoryLayout.LoaderMappingsSize * MM_PAGE_SIZE); /* Update session space start address */ MemoryLayout.SessionSpaceStart = (PVOID)((ULONGLONG)MemoryLayout.SessionSpaceEnd - MemoryLayout.SessionSpaceSize * MM_PAGE_SIZE); /* Compute system PTE size */ ComputeSystemPteSize(&NumberOfSystemPtes); /* Compute the initial and maximum non-paged pool sizes */ ComputeNonPagedPoolSize(&MemoryLayout.NonPagedPoolSize); ComputeMaximumNonPagedPoolSize(&MaximumNonPagedPoolSize); /* Compute paged pool size */ ComputePagedPoolSize(&MemoryLayout.PagedPoolSize); /* Position the PFN database right after the loader mappings */ MemoryLayout.PfnDatabase = (PMMPFN)MemoryLayout.LoaderMappingsEnd; /* Compute the PFN database end address */ PfnDatabaseEnd = (ULONG_PTR)MemoryLayout.PfnDatabase + (MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); /* Position the initial non-paged pool immediately after the PFN database */ MemoryLayout.NonPagedPoolStart = (PVOID)PfnDatabaseEnd; /* Check if the calculated non-paged pool size fits in the KVA */ if((MemoryLayout.NonPagedPoolSize * MM_PAGE_SIZE) > ((ULONG_PTR)MemoryLayout.SessionSpaceStart - (ULONG_PTR)MemoryLayout.NonPagedPoolStart)) { /* Set the final size for the non-paged pool */ MemoryLayout.NonPagedPoolSize = ((ULONG_PTR)MemoryLayout.NonPagedPoolEnd - (ULONG_PTR)MemoryLayout.NonPagedPoolStart) / MM_PAGE_SIZE; } /* Set the final non-paged pool end address */ MemoryLayout.NonPagedPoolEnd = (PVOID)((ULONG_PTR)MemoryLayout.NonPagedPoolStart + MemoryLayout.NonPagedPoolSize * MM_PAGE_SIZE); /* Check if non-paged expansion pool overflows */ if((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart + MaximumNonPagedPoolSize * MM_PAGE_SIZE >= (ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart) { /* Check if non-paged expansion pool fits */ if((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart + MaximumNonPagedPoolSize * MM_PAGE_SIZE <= (ULONG_PTR)MemoryLayout.NonPagedExpansionPoolEnd) { /* Set new non-paged expansion pool end address */ MemoryLayout.NonPagedExpansionPoolEnd = (PVOID)((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart + MaximumNonPagedPoolSize * MM_PAGE_SIZE); } } /* Compute non-paged expansion pool size */ MemoryLayout.NonPagedExpansionPoolSize = ((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolEnd - (ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart) / MM_PAGE_SIZE; } ================================================ FILE: xtoskrnl/mm/i686/pagemap.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/i686/pagemap.cc * DESCRIPTION: Low-level support for i686 page map manipulation * DEVELOPERS: Aiken Harris */ #include /** * Checks if the given address is canonical. * * @param VirtualAddress * Specifies the virtual address to check. * * @return This routine returns TRUE, as all addresses in i686 are canonical. * * @since XT 1.0 */ XTAPI BOOLEAN MM::PageMap::CanonicalAddress(IN PVOID VirtualAddress) { /* All addresses in i686 are canonical */ return TRUE; } /** * Gets Page Map Level (PML) for current paging mode. * * @return This routine returns the page map level. * * @since XT 1.0 */ XTAPI USHORT MM::PageMap::GetPageMapLevel() { return PageMapInfo.Xpa ? 3 : 2; } /** * Gets the address of the PDE (Page Directory Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PDE. * * @return This routine returns the address of the PDE. * * @since XT 1.0 */ XTAPI PMMPDE MM::PageMap::GetPdeAddress(IN PVOID Address) { ULONG Offset; /* Calculate offset and return PDE address */ Offset = ((((ULONG_PTR)(Address)) >> PageMapInfo.PdiShift) << PageMapInfo.PteShift); return (PMMPDE)(PageMapInfo.PdeBase + Offset); } /** * Gets the Offset of the PDE (Page Directory Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PDE. * * @return This routine returns the Offset of the PDE. * * @since XT 1.0 */ XTAPI ULONG MM::PageMap::GetPdeOffset(IN PVOID Address) { /* Return PDE Offset */ return ((((ULONG_PTR)(Address)) >> PageMapInfo.PdiShift) & (PageMapInfo.Xpa ? 0x1FF : 0x3FF)); } /** * Gets the address of the PPE (Page Directory Pointer Table Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PDE. * * @return This routine returns the address of the PPE. * * @since XT 1.0 */ XTAPI PMMPPE MM::PageMap::GetPpeAddress(IN PVOID Address) { /* Return zero */ return (PMMPPE)0; } /** * Gets the offset of the PPE (Page Directory Pointer Table Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PPE. * * @return This routine returns the offset of the PPE. * * @since XT 1.0 */ XTAPI ULONG MM::PageMap::GetPpeOffset(IN PVOID Address) { /* Return zero */ return 0; } /** * Gets the virtual address that is mapped by a given Page Directory Pointer Table Entry. * * @param PpePointer * Specifies the virtual address of the PPE. * * @return This routine returns the virtual address mapped by the PPE. * * @since XT 1.0 */ XTAPI PVOID MM::PageMap::GetPpeVirtualAddress(IN PMMPPE PpePointer) { /* Return zero */ return (PVOID)0; } /** * Gets the address of the PTE (Page Table Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PTE. * * @return This routine returns the address of the PTE. * * @since XT 1.0 */ XTAPI PMMPTE MM::PageMap::GetPteAddress(IN PVOID Address) { ULONG Offset; /* Calculate offset and return PTE address */ Offset = ((((ULONG_PTR)(Address)) >> MM_PTI_SHIFT) << PageMapInfo.PteShift); return (PMMPTE)(PageMapInfo.PteBase + Offset); } /** * Gets the Offset of the PTE (Page Table Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PTE. * * @return This routine returns the Offset of the PTE. * * @since XT 1.0 */ XTAPI ULONG MM::PageMap::GetPteOffset(IN PVOID Address) { /* Return PTE Offset */ return ((((ULONG_PTR)(Address)) >> MM_PTI_SHIFT) & (PageMapInfo.Xpa ? 0x1FF : 0x3FF)); } /** * Gets the status of Extended Paging Address (XPA) mode. * * @return This routine returns TRUE if XPA is enabled, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::PageMap::GetXpaStatus() { return PageMapInfo.Xpa; } /** * Advances a PTE pointer by a given number of entries, considering the actual PTE size for PML2. * * @param Pte * The PTE pointer to advance. * * @param Count * The number of PTE entries to advance by. * * @return This routine returns the advanced PTE pointer. * * @since XT 1.0 */ XTAPI PMMPTE MM::PageMapBasic::AdvancePte(IN PMMPTE Pte, IN ULONG Count) { /* Return advanced PTE pointer */ return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPML2_PTE))); } /** * Clears the contents of a page table entry (PTE). * * @param PtePointer * Pointer to the page table entry (PTE) to be cleared. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapBasic::ClearPte(IN PMMPTE PtePointer) { /* Clear PTE */ PtePointer->Pml2.Long = 0; } /** * Gets the next entry in a PTE list. * * @param Pte * The PTE pointer to get the next entry from. * * @return This routine returns the next entry in the PTE list. * * @since XT 1.0 */ XTAPI ULONG_PTR MM::PageMapBasic::GetNextEntry(IN PMMPTE Pte) { /* Return next entry in PTE list, translating the hardware limit (0xFFFFF) to the logical sentinel (MAXULONG) */ return (Pte->Pml2.List.NextEntry == 0xFFFFF) ? MAXULONG : Pte->Pml2.List.NextEntry; } /** * Advances a PTE pointer, considering the actual PTE size for PML2. * * @param Pte * The PTE pointer to advance. * * @return The advanced PTE pointer. * * @since XT 1.0 */ XTAPI PMMPTE MM::PageMapBasic::GetNextPte(IN PMMPTE Pte) { /* Return advanced PTE pointer */ return AdvancePte(Pte, 1); } /** * Checks if a PTE list contains only one entry. * * @param Pte * The PTE pointer to check. * * @return This routine returns TRUE if the PTE list has only one entry, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::PageMapBasic::GetOneEntry(IN PMMPTE Pte) { /* Return one entry status */ return Pte->Pml2.List.OneEntry; } /** * Gets the page frame number from a corresponding PTE. * * @param Pte * The PTE pointer to get the page frame number from. * * @return This routine returns the page frame number. * * @since XT 1.0 */ XTAPI PFN_NUMBER MM::PageMapBasic::GetPageFrameNumber(IN PMMPTE Pte) { return Pte->Pml2.Hardware.PageFrameNumber; } /** * Gets the virtual address that is mapped by a given Page Directory Entry. * * @param PdePointer * Specifies the address of the PDE. * * @return This routine returns the virtual address mapped by the PDE. * * @since XT 1.0 */ XTAPI PVOID MM::PageMapBasic::GetPdeVirtualAddress(IN PMMPDE PdePointer) { /* Return PDE virtual address */ return ((PVOID)((ULONG)(PdePointer) << 20)); } /** * Gets the entire contents of a PML2 Page Table Entry (PTE) as a single value. * * @param PtePointer * Pointer to the Page Table Entry (PTE) to read. * * @return This routine returns the contents of the PTE as a single value. * * @since XT 1.0 */ XTAPI ULONGLONG MM::PageMapBasic::GetPte(IN PMMPTE PtePointer) { /* Return PTE value */ return (ULONGLONG)PtePointer->Pml2.Long; } /** * Calculates the distance between two PTE pointers. * * @param EndPte * Pointer to the ending Page Table Entry. * * @param StartPte * Pointer to the starting Page Table Entry. * * @return This routine returns a signed value representing the number of PTEs between EndPte and StartPte. * * @since XT 1.0 */ XTAPI LONG MM::PageMapBasic::GetPteDistance(PMMPTE EndPte, PMMPTE StartPte) { /* Return distance between PTE pointers */ return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPML2_PTE); } /** * Gets the size of a PTE for basic paging (PML2). * * @return This routine returns the size of a PTE. * * @since XT 1.0 */ XTAPI ULONG MM::PageMapBasic::GetPteSize(VOID) { /* Return the size of MMPTE */ return sizeof(MMPML2_PTE); } /** * Gets the software protection value of the corresponding Page Table Entry. * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the PTE software protection value. * * @since XT 1.0 */ XTAPI ULONG MM::PageMapBasic::GetPteSoftwareProtection(IN PMMPTE PtePointer) { /* Return PTE software protection value */ return (ULONG)PtePointer->Pml2.Software.Protection; } /** * Gets the software prototype value of the corresponding Page Table Entry. * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the PTE software prototype value. * * @since XT 1.0 */ XTAPI ULONG MM::PageMapBasic::GetPteSoftwarePrototype(IN PMMPTE PtePointer) { /* Return PTE software prototype value */ return (ULONG)PtePointer->Pml2.Software.Prototype; } /** * Gets the software transition value of the corresponding Page Table Entry. * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the PTE software transition value. * * @since XT 1.0 */ XTAPI ULONG MM::PageMapBasic::GetPteSoftwareTransition(IN PMMPTE PtePointer) { /* Return PTE software transition value */ return (ULONG)PtePointer->Pml2.Software.Transition; } /** * Gets the virtual address that is mapped by a given Page Table Entry. * * @param PtePointer * Specifies the virtual address of the PTE. * * @return This routine returns the virtual address mapped by the PTE. * * @since XT 1.0 */ XTAPI PVOID MM::PageMapBasic::GetPteVirtualAddress(IN PMMPTE PtePointer) { /* Return PTE virtual address */ return ((PVOID)((ULONG)(PtePointer) << 10)); } /** * Initializes page map information for basic paging (PML2). * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapBasic::InitializePageMapInfo(VOID) { /* Set PML2 page map information */ PageMapInfo.Xpa = FALSE; /* Set PML2 base addresses */ PageMapInfo.PteBase = MM_PTE_BASE; PageMapInfo.PdeBase = MM_PDE_LEGACY_BASE; /* Set PML2 shift values */ PageMapInfo.PdiShift = MM_PDI_LEGACY_SHIFT; PageMapInfo.PteShift = MM_PTE_LEGACY_SHIFT; } /** * Checks whether the given PML2 page table entry (PTE) is valid. * * @param PtePointer * Pointer to the page table entry (PTE) to check. * * @return Returns TRUE if the entry is valid, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::PageMapBasic::PteValid(IN PMMPTE PtePointer) { /* Check if PTE is valid */ return (BOOLEAN)PtePointer->Pml2.Hardware.Valid; } /** * Sets the next entry in a PTE list. * * @param Pte * The PTE pointer to modify. * * @param Value * The value to set as the next entry. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapBasic::SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value) { /* Set next entry in PTE list, translating the logical sentinel (MAXULONG) to the 20-bit hardware limit (0xFFFFF) */ Pte->Pml2.List.NextEntry = (Value == MAXULONG) ? 0xFFFFF : Value; } /** * Sets the flag indicating whether a PTE list contains only one entry. * * @param Pte * The PTE pointer to modify. * * @param Value * The value to set. TRUE if the list has only one entry, FALSE otherwise. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapBasic::SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value) { /* Set one entry status */ Pte->Pml2.List.OneEntry = Value; } /** * Sets a PML2 page table entry (PTE) with the specified physical page and access flags. * * @param PtePointer * Pointer to the page table entry (PTE) to set. * * @param PageFrameNumber * Physical frame number to map. * * @param AttributesMask * Specifies the attributes mask to apply to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapBasic::SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG AttributesMask) { /* Set PTE */ PtePointer->Pml2.Hardware.PageFrameNumber = PageFrameNumber; PtePointer->Pml2.Hardware.Valid = 1; PtePointer->Pml2.Long |= (ULONG)AttributesMask; } /** * Sets a PML2 page table entry (PTE) with the specified attributes. * * @param PtePointer * Pointer to the page table entry (PTE) to set. * * @param Attributes * Specifies the attributes to apply to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapBasic::SetPte(IN PMMPTE PtePointer, IN ULONGLONG Attributes) { PtePointer->Pml2.Long = (ULONG)Attributes; } /** * Sets caching attributes for a PML2 page table entry (PTE). * * @param PtePointer * Pointer to the page table entry (PTE) to modify. * * @param CacheDisable * Indicates whether caching should be disabled for this page. * * @param WriteThrough * Indicates whether write-through caching should be enabled. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapBasic::SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) { /* Set caching attributes */ PtePointer->Pml2.Hardware.CacheDisable = CacheDisable; PtePointer->Pml2.Hardware.WriteThrough = WriteThrough; } /** * Transitions a Page Table Entry (PTE) to invalid state * * @param PointerPte * Pointer to the page table entry (PTE) to transition. * * @param Protection * Specifies the protection attribute to apply to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapBasic::TransitionPte(IN PMMPTE PointerPte, IN ULONG_PTR Protection) { MMPTE TempPte; /* Set transition PTE */ TempPte.Pml2.Long = PointerPte->Pml2.Long; TempPte.Pml2.Software.Protection = Protection; TempPte.Pml2.Software.Prototype = 0; TempPte.Pml2.Software.Transition = 1; TempPte.Pml2.Software.Valid = 0; /* Write PTE value */ PointerPte->Pml2.Long = TempPte.Pml2.Long; } /** * Writes a PML2 page table entry (PTE) with the specified value. * * @param Pte * Pointer to the page table entry (PTE) to write. * * @param Value * The value to write to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapBasic::WritePte(IN PMMPTE Pte, IN MMPTE Value) { /* Write PTE value */ Pte->Pml2.Long = Value.Pml2.Long; } /** * Advances a PTE pointer by a given number of entries, considering the actual PTE size for PML3. * * @param Pte * The PTE pointer to advance. * * @param Count * The number of PTE entries to advance by. * * @return The advanced PTE pointer. * * @since XT 1.0 */ XTAPI PMMPTE MM::PageMapXpa::AdvancePte(IN PMMPTE Pte, IN ULONG Count) { /* Return advanced PTE pointer */ return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPML3_PTE))); } /** * Clears the contents of a page table entry (PTE). * * @param PtePointer * Pointer to the page table entry (PTE) to be cleared. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapXpa::ClearPte(IN PMMPTE PtePointer) { /* Clear PTE */ PtePointer->Pml3.Long = 0; } /** * Gets the next entry in a PTE list. * * @param Pte * The PTE pointer to get the next entry from. * * @return This routine returns the next entry in the PTE list. * * @since XT 1.0 */ XTAPI ULONG_PTR MM::PageMapXpa::GetNextEntry(IN PMMPTE Pte) { /* Return next entry in PTE list */ return Pte->Pml3.List.NextEntry; } /** * Advances a PTE pointer, considering the actual PTE size for PML3. * * @param Pte * The PTE pointer to advance. * * @return The advanced PTE pointer. * * @since XT 1.0 */ XTAPI PMMPTE MM::PageMapXpa::GetNextPte(IN PMMPTE Pte) { /* Return advanced PTE pointer */ return AdvancePte(Pte, 1); } /** * Checks if a PTE list contains only one entry. * * @param Pte * The PTE pointer to check. * * @return This routine returns TRUE if the PTE list has only one entry, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::PageMapXpa::GetOneEntry(IN PMMPTE Pte) { /* Return one entry status */ return Pte->Pml3.List.OneEntry; } /** * Gets the page frame number from a corresponding PTE. * * @param Pte * The PTE pointer to get the page frame number from. * * @return This routine returns the page frame number. * * @since XT 1.0 */ XTAPI PFN_NUMBER MM::PageMapXpa::GetPageFrameNumber(IN PMMPTE Pte) { return Pte->Pml3.Hardware.PageFrameNumber; } /** * Gets the virtual address that is mapped by a given Page Directory Entry. * * @param PdePointer * Specifies the address of the PDE. * * @return This routine returns the virtual address mapped by the PDE. * * @since XT 1.0 */ XTAPI PVOID MM::PageMapXpa::GetPdeVirtualAddress(IN PMMPDE PdePointer) { /* Return PDE virtual address */ return ((PVOID)((ULONG)(PdePointer) << 18)); } /** * Gets the entire contents of a PML3 Page Table Entry (PTE) as a single value. * * @param PtePointer * Pointer to the Page Table Entry (PTE) to read. * * @return This routine returns the contents of the PTE as a single value. * * @since XT 1.0 */ XTAPI ULONGLONG MM::PageMapXpa::GetPte(IN PMMPTE PtePointer) { /* Return PTE value */ return PtePointer->Pml3.Long; } /** * Calculates the distance between two PTE pointers. * * @param EndPte * Pointer to the ending Page Table Entry. * * @param StartPte * Pointer to the starting Page Table Entry. * * @return This routine returns a signed value representing the number of PTEs between EndPte and StartPte. * * @since XT 1.0 */ XTAPI LONG MM::PageMapXpa::GetPteDistance(PMMPTE EndPte, PMMPTE StartPte) { /* Return distance between PTE pointers */ return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPML3_PTE); } /** * Gets the size of a PTE for XPA paging (PML3). * * @return This routine returns the size of a PTE. * * @since XT 1.0 */ XTAPI ULONG MM::PageMapXpa::GetPteSize(VOID) { /* Return the size of MMPTE */ return sizeof(MMPML3_PTE); } /** * Gets the software protection value of the corresponding Page Table Entry. * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the PTE software protection value. * * @since XT 1.0 */ XTAPI ULONG MM::PageMapXpa::GetPteSoftwareProtection(IN PMMPTE PtePointer) { /* Return PTE software protection value */ return (ULONG)PtePointer->Pml3.Software.Protection; } /** * Gets the software prototype value of the corresponding Page Table Entry. * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the PTE software prototype value. * * @since XT 1.0 */ XTAPI ULONG MM::PageMapXpa::GetPteSoftwarePrototype(IN PMMPTE PtePointer) { /* Return PTE software prototype value */ return (ULONG)PtePointer->Pml3.Software.Prototype; } /** * Gets the software transition value of the corresponding Page Table Entry. * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the PTE software transition value. * * @since XT 1.0 */ XTAPI ULONG MM::PageMapXpa::GetPteSoftwareTransition(IN PMMPTE PtePointer) { /* Return PTE software transition value */ return (ULONG)PtePointer->Pml3.Software.Transition; } /** * Gets the virtual address that is mapped by a given Page Table Entry. * * @param PtePointer * Specifies the virtual address of the PTE. * * @return This routine returns the virtual address mapped by the PTE. * * @since XT 1.0 */ XTAPI PVOID MM::PageMapXpa::GetPteVirtualAddress(IN PMMPTE PtePointer) { /* Return PTE virtual address */ return ((PVOID)((ULONG)(PtePointer) << 9)); } /** * Initializes page map information for basic paging (PML3). * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapXpa::InitializePageMapInfo(VOID) { /* Set PML3 page map information */ PageMapInfo.Xpa = TRUE; /* Set PML3 base addresses */ PageMapInfo.PteBase = MM_PTE_BASE; PageMapInfo.PdeBase = MM_PDE_BASE; /* Set PML3 shift values */ PageMapInfo.PdiShift = MM_PDI_SHIFT; PageMapInfo.PteShift = MM_PTE_SHIFT; } /** * Checks whether the given PML3 page table entry (PTE) is valid. * * @param PtePointer * Pointer to the page table entry (PTE) to check. * * @return Returns TRUE if the entry is valid, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::PageMapXpa::PteValid(IN PMMPTE PtePointer) { return (BOOLEAN)PtePointer->Pml3.Hardware.Valid; } /** * Sets the next entry in a PTE list. * * @param Pte * The PTE pointer to modify. * * @param Value * The value to set as the next entry. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapXpa::SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value) { /* Set next entry in PTE list */ Pte->Pml3.List.NextEntry = Value; } /** * Sets the flag indicating whether a PTE list contains only one entry. * * @param Pte * The PTE pointer to modify. * * @param Value * The value to set. TRUE if the list has only one entry, FALSE otherwise. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapXpa::SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value) { /* Set one entry status */ Pte->Pml3.List.OneEntry = Value; } /** * Sets a PML3 page table entry (PTE) with the specified physical page and access flags. * * @param PtePointer * Pointer to the page table entry (PTE) to set. * * @param PageFrameNumber * Physical frame number to map. * * @param AttributesMask * Specifies the attributes mask to apply to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapXpa::SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG AttributesMask) { /* Set PTE */ PtePointer->Pml3.Hardware.PageFrameNumber = PageFrameNumber; PtePointer->Pml3.Hardware.Valid = 1; PtePointer->Pml3.Long |= AttributesMask; } /** * Sets a PML3 page table entry (PTE) with the specified attributes. * * @param PtePointer * Pointer to the page table entry (PTE) to set. * * @param Attributes * Specifies the attributes to apply to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapXpa::SetPte(IN PMMPTE PtePointer, IN ULONGLONG Attributes) { PtePointer->Pml3.Long = Attributes; } /** * Sets caching attributes for a PML3 page table entry (PTE). * * @param PtePointer * Pointer to the page table entry (PTE) to modify. * * @param CacheDisable * Indicates whether caching should be disabled for this page. * * @param WriteThrough * Indicates whether write-through caching should be enabled. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapXpa::SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) { /* Set caching attributes */ PtePointer->Pml3.Hardware.CacheDisable = CacheDisable; PtePointer->Pml3.Hardware.WriteThrough = WriteThrough; } /** * Transitions a Page Table Entry (PTE) to invalid state * * @param PointerPte * Pointer to the page table entry (PTE) to transition. * * @param Protection * Specifies the protection attribute to apply to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapXpa::TransitionPte(IN PMMPTE PointerPte, IN ULONG_PTR Protection) { MMPTE TempPte; /* Set transition PTE */ TempPte.Pml3.Long = PointerPte->Pml3.Long; TempPte.Pml3.Software.Protection = Protection; TempPte.Pml3.Software.Prototype = 0; TempPte.Pml3.Software.Transition = 1; TempPte.Pml3.Software.Valid = 0; /* Write PTE value */ PointerPte->Pml3.Long = TempPte.Pml3.Long; } /** * Writes a PML3 page table entry (PTE) with the specified value. * * @param Pte * Pointer to the page table entry (PTE) to write. * * @param Value * The value to write to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::PageMapXpa::WritePte(IN PMMPTE Pte, IN MMPTE Value) { /* Write PTE value */ Pte->Pml3.Long = Value.Pml3.Long; } ================================================ FILE: xtoskrnl/mm/i686/paging.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/i686/paging.cc * DESCRIPTION: Architecture dependent paging support * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Checks if eXtended Physical Addressing (XPA) is enabled. * * @return This routine returns TRUE if PAE is enabled, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Paging::GetExtendedPhysicalAddressingStatus(VOID) { /* Check if PAE is enabled */ return ((AR::CpuFunctions::ReadControlRegister(4) & CR4_PAE) != 0) ? TRUE : FALSE; } /** * Maps a specific virtual address to a specific physical page frame (i686 specific). * * @param VirtualAddress * The virtual address to map. * * @param PageFrameNumber * The physical frame number to back the virtual address. * * @param Attributes * Specifies the attributes (protections, caching) to apply to the PTE. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Paging::MapVirtualAddress(IN PVOID VirtualAddress, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG Attributes) { MMPTE TemplatePte; PMMPTE PointerPte; /* Initialize the template PTE */ MM::Paging::ClearPte(&TemplatePte); MM::Paging::SetPte(&TemplatePte, 0, Attributes | MM_PTE_CACHE_ENABLE); /* Check if XPA is enabled */ if(MM::Paging::GetXpaStatus()) { /* Map Page Directory Pointer Table */ MM::Pte::MapPPE(VirtualAddress, VirtualAddress, (PMMPPE)&TemplatePte); } /* Map Page Directory Entry */ MM::Pte::MapPDE(VirtualAddress, VirtualAddress, (PMMPDE)&TemplatePte); /* Get PTE address */ PointerPte = MM::Paging::GetPteAddress(VirtualAddress); /* Initialize the template PTE */ MM::Paging::ClearPte(&TemplatePte); MM::Paging::SetPte(&TemplatePte, PageFrameNumber, Attributes); /* Write the PTE */ MM::Paging::WritePte(PointerPte, TemplatePte); /* Flush the TLB to reflect the changes */ MM::Paging::FlushTlb(); /* Return success */ return STATUS_SUCCESS; } /** * Fills a section of memory with zeroes like RtlZeroMemory(), but in more efficient way. * * @param Address * Supplies an address of the page to be filled with zeroes. * * @param Size * Number of bytes to be filled with zeros. This always should be a multiply of page size. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID MM::Paging::ZeroPages(IN PVOID Address, IN ULONG Size) { __asm__ volatile("xor %%eax, %%eax\n" "rep stosb" : "=D"(Address), "=c"(Size) : "0"(Address), "1"(Size), "a"(0) : "memory"); } ================================================ FILE: xtoskrnl/mm/i686/pfault.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/i686/pfault.cc * DESCRIPTION: Page fault support for i686 architecture * DEVELOPERS: Aiken Harris */ #include /** * Evaluates the PDE for for paged pool and per-session mappings. * * @param VirtualAddress * Specifies the virtual address to verify. * * @return This routine returns ACCESS_VIOLATION on PML3 or status code on PML2. */ XTFASTCALL XTSTATUS MM::PageFault::CheckPdeForPagedPool(IN PVOID VirtualAddress) { /* Check if XPA is enabled */ if(MM::Paging::GetXpaStatus()) { /* Access violation for PML3 */ return STATUS_ACCESS_VIOLATION; } /* Unimplemented path for PML2 */ UNIMPLEMENTED; /* Temporarily, just return access violation */ return STATUS_ACCESS_VIOLATION; } ================================================ FILE: xtoskrnl/mm/i686/pfn.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/i686/pfn.cc * DESCRIPTION: Physical Frame Number for i686 support * DEVELOPERS: Aiken Harris * Rafal Kupiec */ #include /** * Allocates and initializes page directory structures for a range of PDEs. * * @param StartingPde * Supplies a pointer to the first PDE in the range to initialize. * * @param EndingPde * Supplies a pointer to the last PDE in the range to initialize. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::InitializePageDirectory(IN PMMPDE StartingPde, IN PMMPDE EndingPde) { /* Nothing to do */ } /** * Initializes the PFN database by mapping virtual memory and populating entries. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::InitializePfnDatabase(VOID) { PLOADER_MEMORY_DESCRIPTOR Descriptor; PKERNEL_INITIALIZATION_BLOCK InitializationBlock; PLIST_ENTRY ListEntry; PMMMEMORY_LAYOUT MemoryLayout; PUCHAR PfnDatabaseEnd; PMMPTE ValidPte; /* Raise runlevel and acquire PFN lock */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); /* Get the kernel initialization block */ InitializationBlock = KE::BootInformation::GetInitializationBlock(); /* Get memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Get the PFN database size and calculate the end of the PFN database virtual address space */ PfnDatabaseEnd = (PUCHAR)MemoryLayout->PfnDatabase + (MemoryLayout->PfnDatabaseSize * MM_PAGE_SIZE) - 1; /* Get a template PTE for mapping the PFN database pages */ ValidPte = MM::Pte::GetValidPte(); /* Map the Page Directory and Page Directory Pointer tables for the PFN database */ MM::Pte::MapPDE(MemoryLayout->PfnDatabase, PfnDatabaseEnd, ValidPte); MM::Pte::MapPTE(MemoryLayout->PfnDatabase, PfnDatabaseEnd, ValidPte); /* Zero PFN database virtual space */ RTL::Memory::ZeroMemory(MemoryLayout->PfnDatabase, MemoryLayout->PfnDatabaseSize * MM_PAGE_SIZE); /* Initialize the color tables */ MM::Colors::InitializeColorTables(); /* Iterate over memory descriptors to map the PFN database and initialize entries */ ListEntry = InitializationBlock->MemoryDescriptorListHead.Flink; while(ListEntry != &InitializationBlock->MemoryDescriptorListHead) { /* Get the descriptor */ Descriptor = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_DESCRIPTOR, ListEntry); /* Skip invisible memory regions */ if(MM::Manager::VerifyMemoryTypeInvisible(Descriptor->MemoryType)) { /* Move to the next descriptor and continue */ ListEntry = ListEntry->Flink; continue; } /* Check if this is the modified free descriptor */ if(Descriptor == FreeDescriptor) { /* Switch to the original descriptor */ Descriptor = &OriginalFreeDescriptor; } /* Check if the free memory block that was split is being processed */ if(Descriptor == &OriginalFreeDescriptor) { /* Skip loop processing, free memory is initialized separately */ ListEntry = ListEntry->Flink; continue; } /* Initialize PFNs for this memory range */ ProcessMemoryDescriptor(Descriptor->BasePage, Descriptor->PageCount, Descriptor->MemoryType); /* Move to the next descriptor */ ListEntry = ListEntry->Flink; } /* Initialize PFNs for the free memory */ ProcessMemoryDescriptor(FreeDescriptor->BasePage, FreeDescriptor->PageCount, LoaderFree); /* Initialize PFNs for the physical pages backing the PFN database */ ProcessMemoryDescriptor(OriginalFreeDescriptor.BasePage, FreeDescriptor->BasePage - OriginalFreeDescriptor.BasePage, LoaderMemoryData); /* Restore original free descriptor */ *FreeDescriptor = OriginalFreeDescriptor; /* Initialize PFNs backing page tables */ InitializePageTablePfns(); } /** * Initializes PFN database entries for the system page tables. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::InitializePageTablePfns(VOID) { PFN_NUMBER PageFrameIndex; PMMPFN Pfn; ULONG RootLevel; PMMPTE RootPte; /* Determine root structure based on paging mode */ if(MM::Paging::GetXpaStatus()) { /* XPA enabled, 3-level paging (PAE) */ RootLevel = 3; /* Retrieve the PFN of the PML3 table and its virtual base address */ PageFrameIndex = AR::CpuFunctions::ReadControlRegister(3) >> MM_PAGE_SHIFT; RootPte = (PMMPTE)MM::Paging::GetPpeAddress(NULLPTR); } else { /* XPA disabled, 2-level paging */ RootLevel = 2; /* Retrieve the PFN of the PML2 table and its virtual base address */ PageFrameIndex = AR::CpuFunctions::ReadControlRegister(3) >> MM_PAGE_SHIFT; RootPte = (PMMPTE)MM::Paging::GetPdeAddress(NULLPTR); } /* Initialize the PFN entry for the root page table itself */ Pfn = GetPfnEntry(PageFrameIndex); if(Pfn) { /* Initialize the PFN entry */ Pfn->PteAddress = NULLPTR; Pfn->u1.WsIndex = 0; Pfn->u2.ShareCount = 1; Pfn->u3.e1.CacheAttribute = PfnNonCached; Pfn->u3.e1.PageLocation = ActiveAndValid; Pfn->u3.e2.ReferenceCount = 1; Pfn->u4.PteFrame = 0; } /* Start recursive scan from the top level */ if(RootPte) { /* Scan the root page table */ ScanPageTable(RootPte, RootLevel); } } /** * Recursively scans a page table to initialize PFN database entries for active pages. * * @param PointerPte * Pointer to the base of the page table to scan. * * @param Level * The paging level of the table being scanned. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::ScanPageTable(IN PMMPTE PointerPte, IN ULONG Level) { PVOID Address; ULONG Index; PMMPTE NextLevelPte; ULONG PtesPerPage; /* Get the number of PTEs per page */ PtesPerPage = MM::Pte::GetPtesPerPage(); /* Check if PML3 is enabled and current level is PDPT */ if(Level == 3) { /* PAE PDPT has only 4 entries */ PtesPerPage = 4; } /* Iterate through all entries in the current page table */ for(Index = 0; Index < PtesPerPage; Index++) { /* Check if the page table entry is present */ if(MM::Paging::PteValid(PointerPte)) { /* Mark the PFN pointed to by this entry as active */ LinkPfnForPageTable(MM::Paging::GetPageFrameNumber(PointerPte), PointerPte); /* Recurse to the next level, if this is not a leaf node (PTE) */ if(Level > 1) { /* Calculate the virtual address mapped by this entry to find the next table */ switch(Level) { case 3: /* Calculate PDE */ Address = MM::Paging::GetPpeVirtualAddress(PointerPte); NextLevelPte = (PMMPTE)MM::Paging::GetPdeAddress(Address); break; case 2: /* Calculate PTE */ Address = MM::Paging::GetPdeVirtualAddress(PointerPte); NextLevelPte = (PMMPTE)MM::Paging::GetPteAddress(Address); break; default: /* Nothing to calculate, return NULLPTR */ NextLevelPte = NULLPTR; break; } /* Recurse deeper if not at the bottom level (PTE) already */ if(NextLevelPte) { /* Recursively scan the next level page table */ ScanPageTable(NextLevelPte, Level - 1); } } } /* Move to the next entry in the current table */ PointerPte = MM::Paging::GetNextPte(PointerPte); } } ================================================ FILE: xtoskrnl/mm/i686/pool.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/i686/pool.cc * DESCRIPTION: I686 Memory Manager pool manager * DEVELOPERS: Aiken Harris */ #include /** * Maps the PTE for the base of the non-paged pool. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::MapNonPagedPool(VOID) { PMMMEMORY_LAYOUT MemoryLayout; /* Retrieve memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Map PDE and PTE for the base of the non-paged pool */ MM::Pte::MapPDE(MemoryLayout->NonPagedPoolStart, (PCHAR)MemoryLayout->NonPagedPoolEnd - 1, MM::Pte::GetValidPte()); MM::Pte::MapPTE(MemoryLayout->NonPagedPoolStart, (PCHAR)MemoryLayout->NonPagedPoolEnd - 1, MM::Pte::GetValidPte()); } ================================================ FILE: xtoskrnl/mm/i686/pte.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/i686/pte.cc * DESCRIPTION: Page Table Entry (PTE) for i686 support * DEVELOPERS: Aiken Harris */ #include /** * Checks if the virtual address is valid and mapped in the page tables. * * @param VirtualAddress * The virtual address to check. * * @return This routine returns TRUE if the address is valid, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Pte::AddressValid(IN PVOID VirtualAddress) { /* Check if PDE and PTE are valid */ if(!MM::Paging::PteValid(MM::Paging::GetPdeAddress(VirtualAddress)) || !MM::Paging::PteValid(MM::Paging::GetPteAddress(VirtualAddress))) { /* Invalid PDE or PTE, return FALSE */ return FALSE; } /* Address is valid, return TRUE */ return TRUE; } /** * Retrieves the base virtual address of the system PTEs. * * @return This routine returns a pointer to the first PTE in the system PTE space. * * @since XT 1.0 */ XTAPI PMMPTE MM::Pte::GetSystemPteBaseAddress(VOID) { return MM::Paging::GetPteAddress(NULLPTR); } /** * Performs the initial setup of the system's page table hierarchy. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pte::InitializePageTable(VOID) { PMMPTE EndSpacePte, PointerPte; PMMMEMORY_LAYOUT MemoryLayout; CPUID_REGISTERS CpuRegisters; MMPTE TemplatePte; /* Retrieve current paging mode and memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Get CPU features */ CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES; AR::CpuFunctions::CpuId(&CpuRegisters); /* Check if Paging Global Extensions (PGE) is supported */ if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PGE) { /* Enable the Global Paging (PGE) feature */ AR::CpuFunctions::WriteControlRegister(4, AR::CpuFunctions::ReadControlRegister(4) | CR4_PGE); } /* Get the PD user-space range for both legacy and PAE paging */ PointerPte = (PMMPTE)MM::Paging::GetPdeAddress(0); EndSpacePte = (PMMPTE)MM::Paging::GetPdeAddress(MemoryLayout->UserSpaceEnd); /* Clear all top-level entries mapping the user address space */ while(PointerPte <= EndSpacePte) { MM::Paging::ClearPte(PointerPte); PointerPte = MM::Paging::GetNextPte(PointerPte); } /* Flush the TLB to invalidate all non-global entries */ AR::CpuFunctions::FlushTlb(); /* Create a template PTE for mapping kernel pages */ MM::Paging::ClearPte(&TemplatePte); MM::Paging::SetPte(&TemplatePte, 0, MM_PTE_READWRITE | MM_PTE_CACHE_ENABLE); /* Map the kernel's PD entries */ MM::Pte::MapPDE(MemoryLayout->NonPagedSystemPoolStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte); } /** * Maps a range of virtual addresses at the PPE (Page Directory Pointer Entry) level. * * @param StartAddress * The beginning of the virtual address range to map. * * @param EndAddress * The end of the virtual address range to map. * * @param TemplatePpe * A template PPE to use for creating new entries. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pte::MapPPE(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMPPE TemplatePpe) { /* Just a stub on i686 platform */ return; } ================================================ FILE: xtoskrnl/mm/kpool.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/kpool.cc * DESCRIPTION: Kernel pool memory management * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Allocates a new kernel stack. * * @param Stack * Supplies a pointer to the memory area that will contain a new kernel stack. * * @param StackSize * Supplies the size of the stack to be allocated, in bytes. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::KernelPool::AllocateKernelStack(OUT PVOID *Stack, IN ULONG StackSize) { PFN_COUNT StackPages; PMMPTE PointerPte, StackPte; MMPTE TempPte, InvalidPte; PFN_NUMBER PageFrameIndex; ULONG Index; /* Initialize the output stack pointer to NULLPTR */ *Stack = NULLPTR; /* Convert the requested stack size into a page count */ StackPages = SIZE_TO_PAGES(StackSize); /* Reserve PTEs for the stack pages, plus a guard page */ StackPte = MM::Pte::ReserveSystemPtes(StackPages + 1, SystemPteSpace); if(!StackPte) { /* Failed to reserve PTEs for the new kernel stack */ return STATUS_INSUFFICIENT_RESOURCES; } /* Set up a template for an invalid PTE */ MM::Paging::SetPte(&InvalidPte, 0, MM_PTE_GUARDED); /* Set up a template for a valid, writable stack PTE */ MM::Paging::ClearPte(&TempPte); MM::Paging::SetPte(&TempPte, 0, MM_PTE_READWRITE | MM_PTE_CACHE_ENABLE); /* Acquire the PFN database lock and raise runlevel to DISPATCH_LEVEL */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); /* Start iterating from the base of the reserved PTE block */ PointerPte = StackPte; /* Loop through each page of the stack that needs to be allocated */ for(Index = 0; Index < StackPages; Index++) { /* Advance to the next PTE */ PointerPte = MM::Paging::GetNextPte(PointerPte); /* Allocate a physical page and temporarily mark the PTE as invalid */ PageFrameIndex = MM::Pfn::AllocatePhysicalPage(MM::Colors::GetNextColor()); *PointerPte = InvalidPte; /* Associate the physical page with its corresponding PTE in the PFN database */ MM::Pfn::LinkPfn(PageFrameIndex, PointerPte, TRUE); /* Make the PTE valid, mapping the virtual address to the physical page */ MM::Paging::SetPte(&TempPte, PageFrameIndex, 0); *PointerPte = TempPte; } /* Zero the newly allocated stack memory, skipping the guard page */ RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(MM::Paging::GetNextPte(StackPte)), MM_PAGE_SIZE * StackPages); /* Return a pointer to the top of the new stack */ *Stack = MM::Paging::GetPteVirtualAddress(MM::Paging::AdvancePte(StackPte, StackPages + 1)); return STATUS_SUCCESS; } /** * Allocates a buffer for structures needed by a processor and assigns it to a corresponding CPU. * * @param StructuresData * Supplies a pointer to the memory area that will contain the allocated buffer. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::KernelPool::AllocateProcessorStructures(OUT PVOID *StructuresData) { PVOID ProcessorStructures; XTSTATUS Status; /* Assign memory for processor structures */ Status = MM::Allocator::AllocatePool(NonPagedPool, KPROCESSOR_STRUCTURES_SIZE, &ProcessorStructures); if(Status != STATUS_SUCCESS) { /* Failed to allocate memory, return status code */ return Status; } /* Make sure all structures are zeroed */ RTL::Memory::ZeroMemory(ProcessorStructures, KPROCESSOR_STRUCTURES_SIZE); /* Return pointer to the processor structures */ *StructuresData = ProcessorStructures; /* Return success */ return STATUS_SUCCESS; } /** * Destroys a kernel stack and frees page table entry. * * @param Stack * Supplies a pointer to the memory area containing a kernel stack. * * @param StackSize * Supplies the size of the stack to be freed, in bytes. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::KernelPool::FreeKernelStack(IN PVOID Stack, IN ULONG StackSize) { PFN_COUNT StackPages; PMMPTE PointerPte; ULONG Index; /* Get the PTE for the top of the stack, including the guard page */ PointerPte = MM::Paging::AdvancePte(MM::Paging::GetPteAddress(Stack), -1); /* Convert the stack size into a page count */ StackPages = SIZE_TO_PAGES(StackSize); /* Start a guarded code block */ { /* Acquire the PFN database lock */ KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); /* Loop through each page of the stack that needs to be freed */ for(Index = 0; Index < StackPages; Index++) { /* Ensure the PTE is valid */ if(MM::Paging::PteValid(PointerPte)) { /* Free the physical page */ MM::Pfn::FreePhysicalPage(PointerPte); } /* Advance to the next PTE */ PointerPte = MM::Paging::AdvancePte(PointerPte, -1); } } /* Release all system PTEs used by the stack, including the guard page */ MM::Pte::ReleaseSystemPtes(PointerPte, StackPages + 1, SystemPteSpace); } /** * Destroys an unused set of processor structures. * * @param StructuresData * Supplies a pointer to the memory area containing the allocated buffer. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::KernelPool::FreeProcessorStructures(IN PVOID StructuresData) { /* Check if the provided pointer is valid */ if(StructuresData != NULLPTR) { /* Release the contiguous memory block back */ MM::Allocator::FreePool(StructuresData); } } ================================================ FILE: xtoskrnl/mm/mmgr.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/mmgr.cc * DESCRIPTION: Memory Manager * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Computes the size of the boot image. * * @param BootImageSize * Supplies a pointer to a variable that will receive the size of the boot image in pages. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::ComputeBootImageSize(OUT PPFN_NUMBER BootImageSize) { PKERNEL_INITIALIZATION_BLOCK InitializationBlock; PFN_NUMBER ImageSize; ULONG_PTR Alignment; /* Get the kernel initialization block */ InitializationBlock = KE::BootInformation::GetInitializationBlock(); /* Calculate the alignment based on the PTE size */ Alignment = ((MM_PAGE_SIZE / MM::Paging::GetPteSize()) * MM_PAGE_SIZE); /* Calculate the size of the boot image */ ImageSize = InitializationBlock->BootImageSize * MM_PAGE_SIZE; ImageSize = (ImageSize + Alignment - 1) & ~(Alignment - 1); /* Return number of pages used by the boot image */ *BootImageSize = ImageSize / MM_PAGE_SIZE; } /** * Retrieves the amount of total available memory in the system. * * @return This routine returns the amount of available memory in the system in megabytes. * * @since XT 1.0 */ XTAPI ULONG_PTR MM::Manager::GetInstalledMemorySize(VOID) { /* Return the amount of installed memory */ return (MM::Pfn::GetNumberOfPhysicalPages() * MM_PAGE_SIZE) / 1048576; } /** * Retrieves a pointer to the system's virtual memory layout structure. * * @return This routine returns a pointer to the memory layout structure. * * @since XT 1.0 */ XTAPI PMMMEMORY_LAYOUT MM::Manager::GetMemoryLayout(VOID) { /* Return a pointer to the global memory layout structure */ return &MemoryLayout; } /** * Retrieves the number of system PTEs. * * @return This routine returns the number of system PTEs. * * @since XT 1.0 */ XTAPI PFN_NUMBER MM::Manager::GetNumberOfSystemPtes(VOID) { return NumberOfSystemPtes; } /** * Initializes and returns the system physical memory descriptor block. * * @return This routine returns a pointer to the structure representing the system usable physical memory block. * * @since XT 1.0 */ XTAPI PPHYSICAL_MEMORY_DESCRIPTOR MM::Manager::GetPhysicalMemoryBlock(VOID) { PPHYSICAL_MEMORY_DESCRIPTOR PrimaryBuffer, SecondaryBuffer; PKERNEL_INITIALIZATION_BLOCK InitializationBlock; PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor; PFN_NUMBER PageFrameNumer, NumberOfPages; ULONG DescriptorCount, RunCount; PLIST_ENTRY ListEntry; XTSTATUS Status; /* Check if the physical memory block has already been initialized */ if(!PhysicalMemoryBlock) { /* Reset local tracking variables */ DescriptorCount = 0; NumberOfPages = 0; PageFrameNumer = -1; RunCount = 0; /* Retrieve the kernel initialization block */ InitializationBlock = KE::BootInformation::GetInitializationBlock(); /* Iterate through the loader memory descriptor list to determine its size */ ListEntry = InitializationBlock->MemoryDescriptorListHead.Flink; while(ListEntry != &InitializationBlock->MemoryDescriptorListHead) { /* Count this descriptor */ DescriptorCount++; /* Go to the next descriptor */ ListEntry = ListEntry->Flink; } /* Ensure the memory descriptor list is not empty */ if(DescriptorCount == 0) { /* Fail gracefully if no memory descriptors were found, by returning NULLPTR */ return NULLPTR; } /* Allocate a primary buffer sized for the maximum possible number of runs */ Status = MM::Allocator::AllocatePool(NonPagedPool, sizeof(PHYSICAL_MEMORY_DESCRIPTOR) + sizeof(PHYSICAL_MEMORY_RUN) * (DescriptorCount - 1), (PVOID*)&PrimaryBuffer, SIGNATURE32('M', 'M', 'g', 'r')); if(Status != STATUS_SUCCESS || !PrimaryBuffer) { /* Primary pool allocation failed, return NULLPTR */ return NULLPTR; } /* Traverse the memory descriptor list a second time to build the map */ ListEntry = InitializationBlock->MemoryDescriptorListHead.Flink; while(ListEntry != &InitializationBlock->MemoryDescriptorListHead) { /* Resolve the memory descriptor record from the current list entry */ MemoryDescriptor = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_DESCRIPTOR, ListEntry); /* Filter out bad, reserved, or invisible memory types */ if((MemoryDescriptor->MemoryType < LoaderMaximum) && (MemoryDescriptor->MemoryType != LoaderBad) && !VerifyMemoryTypeInvisible(MemoryDescriptor->MemoryType)) { /* Accumulate the total number of usable physical pages */ NumberOfPages += MemoryDescriptor->PageCount; /* Check if the current descriptor is contiguous with the previous run */ if(RunCount > 0 && MemoryDescriptor->BasePage == PageFrameNumer) { /* Coalesce the contiguous descriptor into the existing physical run */ PrimaryBuffer->Run[RunCount - 1].PageCount += MemoryDescriptor->PageCount; PageFrameNumer += MemoryDescriptor->PageCount; } else { /* Start a new physical run with the new descriptor's boundaries */ PrimaryBuffer->Run[RunCount].BasePage = MemoryDescriptor->BasePage; PrimaryBuffer->Run[RunCount].PageCount = MemoryDescriptor->PageCount; /* Update the expected next page frame number for future contiguity checks */ PageFrameNumer = PrimaryBuffer->Run[RunCount].BasePage + PrimaryBuffer->Run[RunCount].PageCount; /* Increment the total number of distinct physical memory runs */ RunCount++; } } /* Go to the next descriptor */ ListEntry = ListEntry->Flink; } /* Check if the buffer can be shrunk due to coalesced memory runs */ if(DescriptorCount > RunCount) { /* Allocate a secondary, more tightly sized buffer to reduce memory footprint */ Status = MM::Allocator::AllocatePool(NonPagedPool, sizeof(PHYSICAL_MEMORY_DESCRIPTOR) + sizeof(PHYSICAL_MEMORY_RUN) * (RunCount - 1), (PVOID*)&SecondaryBuffer, SIGNATURE32('M', 'M', 'g', 'r')); if(Status == STATUS_SUCCESS && SecondaryBuffer) { /* Copy the coalesced runs from the oversized primary buffer */ RtlCopyMemory(SecondaryBuffer->Run, PrimaryBuffer->Run, sizeof(PHYSICAL_MEMORY_RUN) * RunCount); /* Free the primary buffer */ MM::Allocator::FreePool(PrimaryBuffer, SIGNATURE32('M', 'M', 'g', 'r')); /* Update the primary buffer pointer */ PrimaryBuffer = SecondaryBuffer; } } /* Populate the final metadata and save the physical memory block globally */ PrimaryBuffer->NumberOfRuns = RunCount; PrimaryBuffer->NumberOfPages = NumberOfPages; PhysicalMemoryBlock = PrimaryBuffer; } /* Return a pointer to the physical memory block */ return PhysicalMemoryBlock; } /** * Performs an early initialization of the XTOS Memory Manager. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Manager::InitializeMemoryManager(VOID) { /* Scan memory descriptors provided by the boot loader */ MM::Pfn::ScanMemoryDescriptors(); /* Check if there are enough physical pages */ if(MM::Pfn::GetNumberOfPhysicalPages() < MM_MINIMUM_PHYSICAL_PAGES) { /* Insufficient physical pages, kernel panic */ DebugPrint(L"Insufficient physical pages! Install additional memory\n"); KE::Crash::Panic(0x7D, MM::Pfn::GetNumberOfPhysicalPages(), MM_MINIMUM_PHYSICAL_PAGES, 0x0, 0x2); } /* Compute page colors to reduce CPU cache conflicts */ MM::Colors::ComputePageColoring(); /* Initialize and dump memory layout */ InitializeMemoryLayout(); DumpMemoryLayout(); /* Initialize PTE template */ MM::Pte::InitializeSystemPte(); /* Initialize page table */ MM::Pte::InitializePageTable(); /* Initialize system PTE space */ MM::Pte::InitializeSystemPteSpace(); /* Initialize memory pool security */ MM::Pool::InitializePoolSecurity(); /* Initialize non-paged pool */ MM::Pool::InitializeNonPagedPool(); /* Initialize PFN database */ MM::Pfn::InitializePfnDatabase(); /* Initialize allocations tracking tables */ MM::Allocator::InitializeAllocationsTracking(); MM::Allocator::InitializeBigAllocationsTracking(); /* Initialize PFN bitmap */ MM::Pfn::InitializePfnBitmap(); /* Initialize paged pool */ MM::Pool::InitializePagedPool(); /* Flush TLB */ AR::CpuFunctions::FlushTlb(); } /** * Allocates and maps the Kernel Shared Data page to its hardcoded virtual address. * * @return This routine returns status code. * * @since XT 1.0 */ XTAPI XTSTATUS MM::Manager::MapKernelSharedData(VOID) { PHYSICAL_ADDRESS PhysAddr; PMMPTE PtePointer; XTSTATUS Status; /* Allocate one physical page from the hardware pool for the shared data */ Status = MM::HardwarePool::AllocateHardwareMemory(1, FALSE, MM_MAXIMUM_PHYSICAL_ADDRESS, &PhysAddr); if(Status != STATUS_SUCCESS) { /* Memory allocation failed, return error code */ return Status; } /* Retrieve the Page Table Entry (PTE) corresponding to the KSD virtual address */ PtePointer = MM::Paging::GetPteAddress((PVOID)MM_KERNEL_SHARED_DATA_ADDRESS); /* Manually map the corresponding PTE */ MM::Paging::SetPte(PtePointer, (PFN_NUMBER)(PhysAddr.QuadPart >> MM_PAGE_SHIFT), MM_PTE_READWRITE); /* Flush the Translation Lookaside Buffer (TLB) */ MM::Paging::FlushTlb(); /* Zero the page content */ RTL::Memory::ZeroMemory((PVOID)MM_KERNEL_SHARED_DATA_ADDRESS, MM_PAGE_SIZE); /* Return success */ return STATUS_SUCCESS; } /** * Checks whether the specified memory type should be considered as free. * * @param MemoryType * Specifies the memory type to verify. * * @return This routine returns TRUE if the specified memory type should be considered as free, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Manager::VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType) { return ((MemoryType == LoaderFirmwareTemporary) || (MemoryType == LoaderFree) || (MemoryType == LoaderLoadedProgram) || (MemoryType == LoaderOsloaderStack)); } /** * Checks whether the specified memory type should be considered as invisible for the memory manager. * * @param MemoryType * Specifies the memory type to verify. * * @return This routine returns TRUE if the specified memory type should be considered as invisible, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Manager::VerifyMemoryTypeInvisible(LOADER_MEMORY_TYPE MemoryType) { return ((MemoryType == LoaderBBTMemory) || (MemoryType == LoaderFirmwarePermanent) || (MemoryType == LoaderSpecialMemory)); } ================================================ FILE: xtoskrnl/mm/paging.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/paging.cc * DESCRIPTION: Low level page management support * DEVELOPERS: Rafal Kupiec */ #include /** * Advances a PTE pointer by a given number of entries, considering the actual PTE size. * * @param Pte * The PTE pointer to advance. * * @param Count * The number of PTE entries to advance by. * * @return The advanced PTE pointer. * * @since XT 1.0 */ XTAPI PMMPTE MM::Paging::AdvancePte(IN PMMPTE Pte, IN LONG Count) { /* Return advanced PTE pointer */ return PmlRoutines->AdvancePte(Pte, Count); } /** * Checks if the given address is canonical. * * @param VirtualAddress * Specifies the virtual address to check. * * @return This routine returns TRUE if the address is canonical, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Paging::CanonicalAddress(IN PVOID VirtualAddress) { /* Return canonical address status */ return PmlRoutines->CanonicalAddress(VirtualAddress); } /** * Clears the contents of a page table entry (PTE). * * @param PtePointer * Pointer to the page table entry (PTE) to be cleared. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Paging::ClearPte(IN PMMPTE PtePointer) { /* Clear PTE */ PmlRoutines->ClearPte(PtePointer); } /** * Flushes the entire Translation Lookaside Buffer (TLB) on all processors. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Paging::FlushEntireTlb(VOID) { /* Temporarily fallback to FlushTlb() as SMP is not supported yet */ FlushTlb(); } /** * Flushes current Translation Lookaside Buffer (TLB). * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Paging::FlushTlb(VOID) { CPUID_REGISTERS CpuRegisters; BOOLEAN Interrupts; ULONG_PTR Cr4; /* Save interrupts state and disable them */ Interrupts = AR::CpuFunctions::InterruptsEnabled(); AR::CpuFunctions::ClearInterruptFlag(); /* Get CPU features */ CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES; AR::CpuFunctions::CpuId(&CpuRegisters); /* Check if Paging Global Extensions (PGE) is supported */ if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PGE) { /* Read CR4 */ Cr4 = AR::CpuFunctions::ReadControlRegister(4); /* Disable PGE */ AR::CpuFunctions::WriteControlRegister(4, Cr4 & ~CR4_PGE); /* Flush the TLB */ AR::CpuFunctions::FlushTlb(); /* Restore CR4 */ AR::CpuFunctions::WriteControlRegister(4, Cr4); } else { /* Simply flush the TLB */ AR::CpuFunctions::FlushTlb(); } /* Check if interrupts should be enabled */ if(Interrupts) { /* Re-enable interrupts */ AR::CpuFunctions::SetInterruptFlag(); } } /** * Gets the next entry in a PTE list. * * @param Pte * The PTE pointer to get the next entry from. * * @return This routine returns the next entry in the PTE list. * * @since XT 1.0 */ XTAPI ULONG_PTR MM::Paging::GetNextEntry(IN PMMPTE Pte) { /* Return next entry in PTE list */ return PmlRoutines->GetNextEntry(Pte); } /** * Advances a PTE pointer, considering the actual PTE size. * * @param Pte * The PTE pointer to advance. * * @return The advanced PTE pointer. * * @since XT 1.0 */ XTAPI PMMPTE MM::Paging::GetNextPte(IN PMMPTE Pte) { /* Return advanced PTE pointer */ return PmlRoutines->GetNextPte(Pte); } /** * Checks if a PTE list contains only one entry. * * @param Pte * The PTE pointer to check. * * @return This routine returns TRUE if the PTE list has only one entry, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Paging::GetOneEntry(IN PMMPTE Pte) { /* Return one entry status */ return PmlRoutines->GetOneEntry(Pte); } /** * Gets the page frame number from a corresponding PTE. * * @param Pte * The PTE pointer to get the page frame number from. * * @return This routine returns the page frame number. * * @since XT 1.0 */ XTAPI PFN_NUMBER MM::Paging::GetPageFrameNumber(IN PMMPTE Pte) { return PmlRoutines->GetPageFrameNumber(Pte); } /** * Gets the page map routines for basic paging mode (non-XPA). * * @return This routine returns the address of the object containing non-XPA page map routines. * * @since XT 1.0 */ XTAPI MM::PPAGEMAP MM::Paging::GetPageMapBasicRoutines(VOID) { static MM::PageMapBasic PageMapBasicRoutines; /* Return non-XPA page map routines */ return &PageMapBasicRoutines; } /** * Gets Page Map Level (PML) for current paging mode. * * @return This routine returns the page map level. * * @since XT 1.0 */ XTAPI USHORT MM::Paging::GetPageMapLevel() { return PmlRoutines->GetPageMapLevel(); } /** * Gets the page map routines for eXtended Physical Addressing (XPA) mode. * * @return This routine returns the address of the object containing XPA page map routines. * * @since XT 1.0 */ XTAPI MM::PPAGEMAP MM::Paging::GetPageMapXpaRoutines(VOID) { static MM::PageMapXpa PageMapXpaRoutines; /* Return XPA page map routines */ return &PageMapXpaRoutines; } /** * Gets the address of the PDE (Page Directory Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PDE. * * @return This routine returns the address of the PDE. * * @since XT 1.0 */ XTAPI PMMPDE MM::Paging::GetPdeAddress(IN PVOID Address) { /* Return PDE address */ return PmlRoutines->GetPdeAddress(Address); } /** * Gets the virtual address that is mapped by a given Page Directory Entry. * * @param PdePointer * Specifies the address of the PDE. * * @return This routine returns the virtual address mapped by the PDE. * * @since XT 1.0 */ XTAPI PVOID MM::Paging::GetPdeVirtualAddress(IN PMMPDE PdePointer) { /* Return PTE virtual address */ return PmlRoutines->GetPdeVirtualAddress(PdePointer); } /** * Gets the address of the PPE (Page Directory Pointer Table Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PDE. * * @return This routine returns the address of the PPE. * * @since XT 1.0 */ XTAPI PMMPPE MM::Paging::GetPpeAddress(IN PVOID Address) { /* Return PPE address */ return PmlRoutines->GetPpeAddress(Address); } /** * Gets the virtual address that is mapped by a given Page Directory Pointer Table Entry. * * @param PpePointer * Specifies the address of the PPE. * * @return This routine returns the virtual address mapped by the PPE. * * @since XT 1.0 */ XTAPI PVOID MM::Paging::GetPpeVirtualAddress(IN PMMPPE PpePointer) { /* Return PTE virtual address */ return PmlRoutines->GetPpeVirtualAddress(PpePointer); } /** * Gets the entire contents of a Page Table Entry (PTE) as a single value. * * @param PtePointer * Pointer to the Page Table Entry (PTE) to read. * * @return This routine returns the contents of the PTE as a single value. * * @since XT 1.0 */ XTAPI ULONGLONG MM::Paging::GetPte(IN PMMPTE PtePointer) { /* Return PTE value */ return PmlRoutines->GetPte(PtePointer); } /** * Gets the address of the PTE (Page Table Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PTE. * * @return This routine returns the address of the PTE. * * @since XT 1.0 */ XTAPI PMMPTE MM::Paging::GetPteAddress(IN PVOID Address) { /* Return PTE address */ return PmlRoutines->GetPteAddress(Address); } /** * Calculates the distance between two PTE pointers. * * @param EndPte * Pointer to the ending Page Table Entry. * * @param StartPte * Pointer to the starting Page Table Entry. * * @return This routine returns a signed value representing the number of PTEs between EndPte and StartPte. * * @since XT 1.0 */ XTAPI LONG MM::Paging::GetPteDistance(PMMPTE EndPte, PMMPTE StartPte) { /* Return distance between PTE pointers */ return PmlRoutines->GetPteDistance(EndPte, StartPte); } /** * Gets the size of a PTE. * * @return This routine returns the size of a PTE. * * @since XT 1.0 */ XTAPI ULONG MM::Paging::GetPteSize(VOID) { /* Return the size of MMPTE */ return PmlRoutines->GetPteSize(); } /** * Gets the software protection value of the corresponding Page Table Entry. * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the PTE software protection value. * * @since XT 1.0 */ XTAPI ULONG MM::Paging::GetPteSoftwareProtection(IN PMMPTE PtePointer) { /* Return PTE software protection value */ return PmlRoutines->GetPteSoftwareProtection(PtePointer); } /** * Gets the software prototype value of the corresponding Page Table Entry. * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the PTE software prototype value. * * @since XT 1.0 */ XTAPI ULONG MM::Paging::GetPteSoftwarePrototype(IN PMMPTE PtePointer) { /* Return PTE software prototype value */ return PmlRoutines->GetPteSoftwarePrototype(PtePointer); } /** * Gets the software transition value of the corresponding Page Table Entry. * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the PTE software transition value. * * @since XT 1.0 */ XTAPI ULONG MM::Paging::GetPteSoftwareTransition(IN PMMPTE PtePointer) { /* Return PTE software transition value */ return PmlRoutines->GetPteSoftwareTransition(PtePointer); } /** * Gets the virtual address that is mapped by a given Page Table Entry. * * @param PtePointer * Specifies the address of the PTE. * * @return This routine returns the virtual address mapped by the PTE. * * @since XT 1.0 */ XTAPI PVOID MM::Paging::GetPteVirtualAddress(IN PMMPTE PtePointer) { /* Return PTE virtual address */ return PmlRoutines->GetPteVirtualAddress(PtePointer); } /** * Gets current status of eXtended Physical Addressing (XPA). * * @return This routine returns TRUE if PAE or LA57 (XPA) is enabled, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Paging::GetXpaStatus() { return PmlRoutines->GetXpaStatus(); } /** * Detects if eXtended Physical Addressing (XPA) is enabled and initializes page map support. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Paging::InitializePageMapSupport(VOID) { /* Check if XPA is enabled */ if(GetExtendedPhysicalAddressingStatus()) { /* XPA enabled, use modern paging (PAE / LA57) */ PmlRoutines = GetPageMapXpaRoutines(); } else { /* XPA disabled, use basic paging (PML2 / PML4) */ PmlRoutines = GetPageMapBasicRoutines(); } /* Set page map information */ PmlRoutines->InitializePageMapInfo(); } /** * Checks whether the given PML2 page table entry (PTE) is valid. * * @param PtePointer * Pointer to the page table entry (PTE) to check. * * @return Returns TRUE if the entry is valid, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Paging::PteValid(IN PMMPTE PtePointer) { /* Check if PTE is valid */ return PmlRoutines->PteValid(PtePointer); } /** * Sets the next entry in a PTE list. * * @param Pte * The PTE pointer to modify. * * @param Value * The value to set as the next entry. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Paging::SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value) { /* Set next entry in PTE list */ PmlRoutines->SetNextEntry(Pte, Value); } /** * Sets the flag indicating whether a PTE list contains only one entry. * * @param Pte * The PTE pointer to modify. * * @param Value * The value to set. TRUE if the list has only one entry, FALSE otherwise. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Paging::SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value) { /* Set one entry status */ PmlRoutines->SetOneEntry(Pte, Value); } /** * Sets a Page Table Entry (PTE) with the specified physical page and access flags. * * @param PtePointer * Pointer to the page table entry (PTE) to set. * * @param PageFrameNumber * Physical frame number to map. * * @param AttributesMask * Specifies the attributes mask to apply to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Paging::SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONGLONG AttributesMask) { /* Set PTE */ PmlRoutines->SetPte(PtePointer, PageFrameNumber, AttributesMask); } /** * Sets a Page Table Entry (PTE) with the specified attributes. * * @param PtePointer * Pointer to the page table entry (PTE) to set. * * @param Attributes * Specifies the attributes to apply to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Paging::SetPte(IN PMMPTE PtePointer, IN ULONGLONG Attributes) { PmlRoutines->SetPte(PtePointer, Attributes); } /** * Sets caching attributes for a PML2 page table entry (PTE). * * @param PtePointer * Pointer to the page table entry (PTE) to modify. * * @param CacheDisable * Indicates whether caching should be disabled for this page. * * @param WriteThrough * Indicates whether write-through caching should be enabled. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Paging::SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) { /* Set caching attributes */ PmlRoutines->SetPteCaching(PtePointer, CacheDisable, WriteThrough); } /** * Transitions a Page Table Entry (PTE) to invalid state * * @param PointerPte * Pointer to the page table entry (PTE) to transition. * * @param Protection * Specifies the protection attribute to apply to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Paging::TransitionPte(IN PMMPTE PointerPte, IN ULONG_PTR Protection) { /* Transition PTE */ PmlRoutines->TransitionPte(PointerPte, Protection); } /** * Writes a Page Table Entry (PTE) with the specified value. * * @param Pte * Pointer to the page table entry (PTE) to write. * * @param Value * The value to write to the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Paging::WritePte(IN PMMPTE Pte, IN MMPTE Value) { /* Assign PTE value */ PmlRoutines->WritePte(Pte, Value); } ================================================ FILE: xtoskrnl/mm/pfn.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/pfn.cc * DESCRIPTION: Physical Frame Number (PFN) support * DEVELOPERS: Aiken Harris * Rafal Kupiec */ #include /** * Allocates a block of physical pages for early kernel initialization. * * @param NumberOfPages * The number of physical pages to allocate. * * @return This routine returns the base page frame number (PFN) of the allocated block. * * @since XT 1.0 */ XTAPI PFN_NUMBER MM::Pfn::AllocateBootstrapPages(IN PFN_NUMBER NumberOfPages) { PFN_NUMBER Pfn; /* Check if the largest free memory block has enough pages */ if(NumberOfPages > FreeDescriptor->PageCount) { /* Not enough physical memory available, kernel panic */ DebugPrint(L"Insufficient physical pages! Install additional memory\n"); KE::Crash::Panic(0x7D, NumberOfPhysicalPages, FreeDescriptor->PageCount, OriginalFreeDescriptor.PageCount, NumberOfPages); } /* Allocate pages from the beginning of the free descriptor */ Pfn = FreeDescriptor->BasePage; FreeDescriptor->BasePage += NumberOfPages; FreeDescriptor->PageCount -= NumberOfPages; /* Return the base page frame number of the allocated block */ return Pfn; } /** * Allocates a physical page frame (PFN) from one of the system's free page lists. * * @param Color * The preferred page color, used to optimize CPU cache alignment and reduce cache contention. * * @return This routine returns the Page Frame Number (PFN) of the allocated page. * * @since XT 1.0 */ XTAPI PFN_NUMBER MM::Pfn::AllocatePhysicalPage(IN ULONG Color) { PFN_NUMBER PageNumber; ULONG PagingColorsMask; /* Check if any physical pages are available in the system */ if(!AvailablePages) { /* No physical pages are available in the system, return 0 */ return 0; } /* Retrieve the bitmask used for calculating a page's color */ PagingColorsMask = MM::Colors::GetPagingColorsMask(); /* Attempt to retrieve a page from the colored free page list */ PageNumber = MM::Colors::GetFreePages(FreePageList, Color)->Flink; if(PageNumber == MAXULONG_PTR) { /* No page was found in the colored free page list, check the colored zero page list */ PageNumber = MM::Colors::GetFreePages(ZeroedPageList, Color)->Flink; } /* Attempt to retrieve a page from the colored zero list */ if(PageNumber == MAXULONG_PTR) { /* No page was found in the colored zero page list, check the global free page list */ PageNumber = FreePagesList.Flink; } /* Attempt to retrieve a page from the global free page list */ if(PageNumber == MAXULONG_PTR) { /* No page was found in the global free page list, check the global zero page list */ PageNumber = ZeroedPagesList.Flink; } /* Remove the page from its list and return its PFN */ return UnlinkFreePage(PageNumber, PageNumber & PagingColorsMask); } /** * Calculates the total number of pages required for the PFN database and its associated color tables. * * @param DatabaseSize * A pointer to a variable that will receive the number of pages required for the PFN database. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::ComputePfnDatabaseSize(OUT PPFN_NUMBER DatabaseSize) { PFN_NUMBER PfnDatabaseSize; /* Calculate the total number of pages required for the PFN database */ PfnDatabaseSize = (HighestPhysicalPage + 1) * sizeof(MMPFN); PfnDatabaseSize += (MM::Colors::GetPagingColors() * sizeof(MMCOLOR_TABLES) * 2); PfnDatabaseSize = ROUND_UP(PfnDatabaseSize, MM_PAGE_SIZE); PfnDatabaseSize >>= MM_PAGE_SHIFT; /* Return the PFN database size */ *DatabaseSize = PfnDatabaseSize; } /** * Decrements the global count of available pages. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::DecrementAvailablePages(VOID) { /* Decrement the global count of available pages */ AvailablePages--; } /** * Decrements the reference count of a PFN entry. * * @param PageFrameNumber * A pointer to the PFN database entry for the physical page. * * @param PageFrameIndex * The page frame number of the physical page. * * @param BeginStandbyList * Determines whether the page should be added to the beginning of the standby list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::DecrementReferenceCount(IN PMMPFN PageFrameNumber, IN PFN_NUMBER PageFrameIndex, IN BOOLEAN BeginStandbyList) { /* Decrement the PFN reference count */ PageFrameNumber->u3.e2.ReferenceCount--; /* If other references exist, no further action is needed */ if(PageFrameNumber->u3.e2.ReferenceCount) { /* No further action can be taken */ return; } /* If the reference count is zero, the share count should also be zero */ if(PageFrameNumber->u2.ShareCount) { /* This indicates a bug; crash the system */ KE::Crash::Panic(0x4E, 0x07, PageFrameIndex, PageFrameNumber->u2.ShareCount, 0); } /* Check if the PTE is marked as being ready for removal */ if((ULONG_PTR)PageFrameNumber->PteAddress & 0x1) { /* Check the page's cache attribute */ if((PageFrameNumber->u3.e1.CacheAttribute != PfnCached) && (PageFrameNumber->u3.e1.CacheAttribute != PfnNotMapped)) { /* Flush the TLB to prevent cache attribute conflicts from stale non-cached mappings */ MM::Paging::FlushEntireTlb(); } /* The page is no longer needed, free it by linking it to the free list */ LinkFreePage(PageFrameIndex); /* No further action is needed */ return; } /* The page is unreferenced and unmapped, so place it on the appropriate list */ if(PageFrameNumber->u3.e1.Modified == 1) { /* Link dirty page to the modified list */ LinkPage(&ModifiedPagesList, PageFrameIndex); } else { /* Check if the page has been marked for removal */ if(PageFrameNumber->u3.e1.RemovalRequested == 1) { /* Update the page location and move it to the bad pages list */ PageFrameNumber->u3.e1.PageLocation = StandbyPageList; LinkPage(&BadPagesList, PageFrameIndex); } else { /* Link clean page to the standby list */ if(BeginStandbyList) { /* Link clean page to the beginning of the standby list */ LinkStandbyPage(PageFrameIndex); } else { /* Link clean page to the end of the standby list */ LinkPage(&StandbyPagesList, PageFrameIndex); } } } } /** * Decrements the share count of a PFN entry, which represents the number of PTEs mapping the page. * * @param PageFrameNumber * A pointer to the PFN database entry for the physical page. * * @param PageFrameIndex * The page frame number of the physical page. * * @param BeginStandbyList * Determines whether the page should be added to the beginning of the standby list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::DecrementShareCount(IN PMMPFN PageFrameNumber, IN PFN_NUMBER PageFrameIndex, IN BOOLEAN BeginStandbyList) { /* Ensure the page is in a valid state */ if((PageFrameNumber->u3.e1.PageLocation != ActiveAndValid) && (PageFrameNumber->u3.e1.PageLocation != StandbyPageList)) { /* This indicates a bug; crash the system */ KE::Crash::Panic(0x4E, 0x99, PageFrameIndex, PageFrameNumber->u3.e1.PageLocation, 0); } /* Decrement the PFN share count */ PageFrameNumber->u2.ShareCount--; /* Check if the share count has dropped to zero */ if(!PageFrameNumber->u2.ShareCount) { /* Check if this is a prototype PTE */ if(PageFrameNumber->u3.e1.PrototypePte) { /* Transition the PTE to invalid state */ MM::Paging::TransitionPte(PageFrameNumber->PteAddress, MM::Paging::GetPteSoftwareProtection(&PageFrameNumber->OriginalPte)); } /* Mark the page as being in a transition state */ PageFrameNumber->u3.e1.PageLocation = TransitionPage; /* Check if there are still outstanding references */ if(PageFrameNumber->u3.e2.ReferenceCount == 1) { /* Check if the PTE is marked as being ready for removal */ if((ULONG_PTR)PageFrameNumber->PteAddress & 0x1) { /* Reset the reference count */ PageFrameNumber->u3.e2.ReferenceCount = 0; /* Check the page's cache attribute */ if((PageFrameNumber->u3.e1.CacheAttribute != PfnCached) && (PageFrameNumber->u3.e1.CacheAttribute != PfnNotMapped)) { /* Flush the TLB to prevent cache attribute conflicts from stale non-cached mappings */ MM::Paging::FlushEntireTlb(); } /* Mark the page as active and valid again */ PageFrameNumber->u3.e1.PageLocation = ActiveAndValid; /* The page is no longer needed, free it by linking it to the free list */ MM::Pfn::LinkFreePage(PageFrameIndex); } else { /* The PTE can not be removed yet, decrement the reference count */ DecrementReferenceCount(PageFrameNumber, PageFrameIndex, BeginStandbyList); } } else { /* There are still some outstanding references, decrement the reference count */ PageFrameNumber->u3.e2.ReferenceCount--; } } } /** * Frees a physical page that is mapped by a given PTE. * * @param PointerPte * A pointer to the Page Table Entry (PTE) that maps the physical page to be freed. * * @return This routine does not return a value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::FreePhysicalPage(IN PMMPTE PointerPte) { PFN_COUNT PageFrameNumber, PageTableFrameNumber; PMMPFN PageFrame, PageTableFrame; /* Get the page frame number from the PTE */ PageFrameNumber = MM::Paging::GetPageFrameNumber(PointerPte); PageFrame = MM::Pfn::GetPfnEntry(PageFrameNumber); /* Get the page table frame number corresponding to the PTE */ PageTableFrameNumber = PageFrame->u4.PteFrame; PageTableFrame = MM::Pfn::GetPfnEntry(PageTableFrameNumber); /* Decrement the share count of the page table */ MM::Pfn::DecrementShareCount(PageTableFrame, PageTableFrameNumber, FALSE); /* Mark the PTE as being ready for removal */ MM::Paging::SetPte(PageFrame->PteAddress, MM::Paging::GetPte(PageFrame->PteAddress) | 1); /* Decrement the share count of the page */ MM::Pfn::DecrementShareCount(PageFrame, PageFrameNumber, FALSE); } /** * Retrieves the number of available physical pages. * * @return This routine returns the number of available physical pages. * * @since XT 1.0 */ XTAPI PFN_NUMBER MM::Pfn::GetAvailablePages(VOID) { /* Return the number of available pages */ return AvailablePages; } /** * Retrieves the highest physical page number (PFN) detected in the system. * * @return This routine returns the highest physical page number. * * @since XT 1.0 */ XTAPI ULONG_PTR MM::Pfn::GetHighestPhysicalPage(VOID) { /* Return the highest physical page number */ return HighestPhysicalPage; } /** * Retrieves the total number of physical pages managed by the system. * * @return Returns the total count of physical memory pages. * * @since XT 1.0 */ XTAPI ULONGLONG MM::Pfn::GetNumberOfPhysicalPages(VOID) { /* Return the number of physical pages */ return NumberOfPhysicalPages; } /** * Retrieves a pointer to the PFN database entry for a given physical page. * * @param Pfn * The Page Frame Number (PFN) to look up. * * @return This routine returns a pointer to the MMPFN structure for the given PFN, or NULLPTR if the PFN is invalid. * * @since XT 1.0 */ XTAPI PMMPFN MM::Pfn::GetPfnEntry(IN PFN_NUMBER Pfn) { PMMMEMORY_LAYOUT MemoryLayout; /* Validate that the PFN is within the range of managed physical memory */ if(Pfn > HighestPhysicalPage) { /* The requested page number is outside the bounds, return NULLPTR */ return NULLPTR; } /* Make sure this page has a PFN entry set */ if(PfnBitMap.Buffer && !RTL::BitMap::TestBit(&PfnBitMap, Pfn)) { /* The requested page number is not set in the bitmap, return NULLPTR */ return NULLPTR; } /* Get the memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Calculate the address of the PFN entry by indexing into the PFN database array and return it */ return &((PMMPFN)MemoryLayout->PfnDatabase)[Pfn]; } /** * Increments the global count of available pages. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::IncrementAvailablePages(VOID) { /* Increment the global count of available pages */ AvailablePages++; } /** * Initializes the PFN bitmap to track available physical memory. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::InitializePfnBitmap(VOID) { PPHYSICAL_MEMORY_DESCRIPTOR PhysicalMemoryBlock; XTSTATUS Status; PVOID BitMap; ULONG Index; /* Retrieve the global physical memory descriptor block */ PhysicalMemoryBlock = MM::Manager::GetPhysicalMemoryBlock(); if(!PhysicalMemoryBlock) { /* Physical memory layout unavailable, kernel panic */ KE::Crash::Panic(0x7D, NumberOfPhysicalPages, LowestPhysicalPage, HighestPhysicalPage, 0x100); } /* Calculate the required bitmap size and allocate memory */ Status = MM::Allocator::AllocatePool(NonPagedPool, (((HighestPhysicalPage + 1) + 31) / 32) * 4, (PVOID *)&BitMap, SIGNATURE32('M', 'M', 'g', 'r')); if(Status != STATUS_SUCCESS || !BitMap) { /* Memory allocation failed, kernel panic */ DebugPrint(L"Insufficient physical pages! Install additional memory\n"); KE::Crash::Panic(0x7D, NumberOfPhysicalPages, LowestPhysicalPage, HighestPhysicalPage, 0x101); } /* Initialize the PFN bitmap structure and clear all bits by default */ RTL::BitMap::InitializeBitMap(&PfnBitMap, (PULONG_PTR)BitMap, (ULONG)HighestPhysicalPage + 1); RTL::BitMap::ClearAllBits(&PfnBitMap); /* Iterate through all contiguous physical memory runs to populate the availability map */ for(Index = 0; Index < PhysicalMemoryBlock->NumberOfRuns; Index++) { /* Ensure the current memory run contains at least one valid page frame */ if((&PhysicalMemoryBlock->Run[Index])->PageCount) { /* Set the corresponding bits to mark these physical pages as available for allocation */ RtlSetBits(&PfnBitMap, (ULONG)(&PhysicalMemoryBlock->Run[Index])->BasePage, (ULONG)(&PhysicalMemoryBlock->Run[Index])->PageCount); } } } /** * Links a physical page to the appropriate free lists. * * @param PageFrameIndex * The Page Frame Number (PFN) of the page to link. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::LinkFreePage(IN PFN_NUMBER PageFrameIndex) { ULONG Color; PMMPFNLIST ListHead; PFN_NUMBER LastPage; PMMPFN ColoredPfn, PfnEntry; PMMCOLOR_TABLES ColorTable; PMMMEMORY_LAYOUT MemoryLayout; /* Get the PFN database entry for the page */ PfnEntry = GetPfnEntry(PageFrameIndex); /* Check if the page is part of a ROM image */ if(PfnEntry->u3.e1.Rom == 1) { /* Mark the page as inactive and clear its links */ PfnEntry->u1.Flink = 0; PfnEntry->u3.e1.PageLocation = 0; /* Do not free ROM pages */ return; } /* Check if the page is marked for removal */ if(PfnEntry->u3.e1.RemovalRequested == 1) { /* Update cache attribute to not mapped */ PfnEntry->u3.e1.CacheAttribute = PfnNotMapped; /* Insert the page into the bad page list instead */ LinkPage(&BadPagesList, PageFrameIndex); /* Do not add it to the free list */ return; } /* Insert the page into the global free list */ ListHead = &FreePagesList; ListHead->Total++; /* Get the current last page on the list */ LastPage = ListHead->Blink; /* Check if the list is not empty */ if(LastPage != MAXULONG_PTR) { /* Link with the previous last page */ GetPfnEntry(LastPage)->u1.Flink = PageFrameIndex; } else { /* Put the page as the first entry */ ListHead->Flink = PageFrameIndex; } /* Set the page as the new tail of the list */ ListHead->Blink = PageFrameIndex; PfnEntry->u1.Flink = MAXULONG_PTR; PfnEntry->u2.Blink = LastPage; PfnEntry->u3.e1.CacheAttribute = PfnNotMapped; PfnEntry->u3.e1.PageLocation = FreePageList; PfnEntry->u4.AweAllocation = 0; PfnEntry->u4.InPageError = 0; PfnEntry->u4.Priority = 3; /* Insert the page into the colored free list */ Color = PageFrameIndex & MM::Colors::GetPagingColorsMask(); ColorTable = MM::Colors::GetFreePages(FreePageList, Color); /* Get the memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Check if the colored list is empty */ if(ColorTable->Flink == MAXULONG_PTR) { /* Put the page as the first entry */ ColorTable->Flink = PageFrameIndex; PfnEntry->u4.PteFrame = MM_PFN_PTE_FRAME; } else { /* Get the current last page on the colored list */ ColoredPfn = (PMMPFN)ColorTable->Blink; /* Link with the previous last page */ MM::Paging::SetPte(&ColoredPfn->OriginalPte, PageFrameIndex); PfnEntry->u4.PteFrame = ColoredPfn - (PMMPFN)MemoryLayout->PfnDatabase; } /* Set the page as the new tail of the colored list */ ColorTable->Blink = PfnEntry; ColorTable->Count++; MM::Paging::SetPte(&PfnEntry->OriginalPte, MAXULONG_PTR); /* Increment number of available pages */ IncrementAvailablePages(); } /** * Links a physical page to the appropriate list. * * @param ListHead * Pointer to the list head. * * @param PageFrameIndex * The Page Frame Number (PFN) of the page to link. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::LinkPage(IN PMMPFNLIST ListHead, IN PFN_NUMBER PageFrameIndex) { PMMCOLOR_TABLES ColorHead; MMPAGELISTS ListName; PMMPFN PageFrame; /* Get the memory layout */ PMMMEMORY_LAYOUT MemoryLayout = MM::Manager::GetMemoryLayout(); /* Get the PFN database entry for the target page */ PageFrame = &((PMMPFN)MemoryLayout->PfnDatabase)[PageFrameIndex]; /* Get the list name */ ListName = ListHead->ListName; /* Handle pages being linked to the modified or standby lists */ if(ListName == ModifiedPageList || ListName == StandbyPageList) { /* Detect an invalid prototype/transition PTE state */ if(!MM::Paging::GetPteSoftwarePrototype(&PageFrame->OriginalPte) && MM::Paging::GetPteSoftwareTransition(&PageFrame->OriginalPte)) { /* Crash system due to corrupted PFN/PTE state */ KE::Crash::Panic(0x1A, 0x8888, 0, 0, 0); } } /* Check if the page is ROM */ if(PageFrame->u3.e1.Rom == 1) { /* Link the page to the ROM list */ ListHead = &RomPagesList; ListHead->Total++; /* Append the page to the end of the ROM list */ if(ListHead->Blink != MAXULONG_PTR) { /* Update the previous tail to point to this page */ (&((PMMPFN)MemoryLayout->PfnDatabase)[ListHead->Blink])->u1.Flink = PageFrameIndex; } else { /* Initialize the list if it was empty */ ListHead->Flink = PageFrameIndex; } /* Update list tail and PFN linkage */ ListHead->Blink = PageFrameIndex; PageFrame->u1.Flink = MAXULONG_PTR; PageFrame->u2.Blink = ListHead->Blink; PageFrame->u3.e1.PageLocation = ListName; /* ROM pages require no further processing */ return; } /* Account for the page being inserted into the target list */ ListHead->Total++; /* Redirect modified pages to the per-color modified list */ if(ListHead == &ModifiedPagesList) { /* Select the modified list matching the page color */ ListHead = MM::Colors::GetModifiedPages(PageFrame->u3.e1.PageColor); ListHead->Total++; } else if((PageFrame->u3.e1.RemovalRequested == 1) && (ListName <= StandbyPageList)) { /* Undo the insertion into the current list */ ListHead->Total--; /* Preserve the standby location for removed pages */ if(ListName == StandbyPageList) { /* Keep the page marked as standby */ PageFrame->u3.e1.PageLocation = StandbyPageList; } /* Mark the page as no longer cache-mapped */ PageFrame->u3.e1.CacheAttribute = PfnNotMapped; /* Move the page to the bad page list */ ListHead = &BadPagesList; ListHead->Total++; ListName = BadPageList; } /* Insert zeroed pages at the head of the list */ if(ListName == ZeroedPageList) { /* Link the page as the new list head */ ListHead->Flink = PageFrameIndex; /* Initialize PFN forward and backward links */ PageFrame->u1.Flink = ListHead->Flink; PageFrame->u2.Blink = MAXULONG_PTR; /* Update the previous head if it exists */ if(ListHead->Flink != MAXULONG_PTR) { /* Fix up the backward link of the old head */ (&((PMMPFN)MemoryLayout->PfnDatabase)[ListHead->Flink])->u2.Blink = PageFrameIndex; } else { /* Set the tail if the list was empty */ ListHead->Blink = PageFrameIndex; } } else { /* Append the page to the tail of the list */ if(ListHead->Blink != MAXULONG_PTR) { /* Link the current tail to the new page */ (&((PMMPFN)MemoryLayout->PfnDatabase)[ListHead->Blink])->u1.Flink = PageFrameIndex; } else { /* Initialize the list if it was empty */ ListHead->Flink = PageFrameIndex; } /* Update list tail */ ListHead->Blink = PageFrameIndex; /* Terminate PFN forward link and set backward link */ PageFrame->u1.Flink = MAXULONG_PTR; PageFrame->u2.Blink = ListHead->Blink; } /* Record the page's current location */ PageFrame->u3.e1.PageLocation = ListName; /* Handle pages that contribute to the available page count */ if(ListName <= StandbyPageList) { /* Increment the system-wide available page counter */ MM::Pfn::IncrementAvailablePages(); /* Select the free list matching the page color */ ColorHead = MM::Colors::GetFreePages(ZeroedPageList, PageFrameIndex & MM::Colors::GetPagingColorsMask()); /* Store the color list linkage in the original PTE */ MM::Paging::SetPte(&PageFrame->OriginalPte, ColorHead->Flink); PageFrame->u4.PteFrame = MM_PFN_PTE_FRAME; /* Insert the page into the color free list */ ColorHead->Flink = PageFrameIndex; /* Update the previous head or initialize the tail */ if(ColorHead->Flink != MAXULONG_PTR) { /* Fix up the PTE frame of the previous entry */ (&((PMMPFN)MemoryLayout->PfnDatabase)[ColorHead->Flink])->u4.PteFrame = PageFrameIndex; } else { /* Set the tail for an empty color list */ ColorHead->Blink = (PVOID)PageFrame; } /* Increment the color list page count */ ColorHead->Count++; } else if(ListName == ModifiedPageList) { /* Modified page insertion logic not implemented yet */ UNIMPLEMENTED; } else if(ListName == ModifiedReadOnlyPageList) { /* Modified read-only page handling not implemented yet */ UNIMPLEMENTED; } } /** * Links a PFN entry to its corresponding PTE and ensures the page table that contains the PTE is resident in memory. * * @param PageFrameIndex * Supplies the index into the PFN database for the page being initialized. * * @param PointerPte * Supplies the pointer to the PTE which maps the physical page. * * @param Modified * Supplies a flag indicating if the page's initial state is modified. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::LinkPfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified) { PMMMEMORY_LAYOUT MemoryLayout; XTSTATUS Status; PMMPFN Pfn; PMMPTE Pte; /* Get the memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Point the PFN to its PTE */ Pfn = &((PMMPFN)MemoryLayout->PfnDatabase)[PageFrameIndex]; Pfn->PteAddress = PointerPte; /* Check if the page is already mapped and in use */ if(MM::Paging::PteValid(PointerPte)) { /* Clear the original PTE information */ MM::Paging::SetPte(&Pfn->OriginalPte, 0, MM_PTE_READWRITE | MM_PTE_CACHE_ENABLE); } else { /* Page is not resident, so save the PTE contents for later use */ Pfn->OriginalPte = *PointerPte; } /* Initialize the PFN database entry for this page */ Pfn->u2.ShareCount = 1; Pfn->u3.e1.Modified = Modified; Pfn->u3.e1.PageLocation = ActiveAndValid; Pfn->u3.e2.ReferenceCount = 1; /* Get the PDE that maps the page table containing this PTE */ Pte = MM::Paging::GetPteAddress(PointerPte); if(!MM::Paging::PteValid(Pte)) { /* Check if page table is resident */ Status = MM::PageFault::CheckPdeForPagedPool(PointerPte); if(Status != STATUS_SUCCESS) { /* Could not make the page table resident, crash system */ KE::Crash::Panic(0x1A, (ULONG_PTR)0x61940, (ULONG_PTR)PointerPte, MM::Paging::GetPageFrameNumber(PointerPte), (ULONG_PTR)MM::Paging::GetPteVirtualAddress(PointerPte)); } } /* Record the page frame of the page table itself */ PageFrameIndex = MM::Paging::GetPageFrameNumber(Pte); Pfn->u4.PteFrame = PageFrameIndex; /* Pin the page table in memory by incrementing its PFN share count */ Pfn = &((PMMPFN)MemoryLayout->PfnDatabase)[PageFrameIndex]; Pfn->u2.ShareCount++; } /** * Initializes the PFN database entry for a physical page that is used as a page table. * * @param PageFrameIndex * The page frame number of the physical page being used as a page table. * * @param PointerPte * A pointer to the higher-level PTE that maps this page table page. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::LinkPfnForPageTable(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte) { PMMPFN Pfn; PMMPDE PointerPde; PVOID EndAddress; /* Retrieve the PFN database entry for the physical page of the page table */ Pfn = GetPfnEntry(PageFrameIndex); /* Calculate the end address of the PFN entry to ensure it's mapped */ EndAddress = (PUCHAR)(Pfn + 1) - 1; /* Validate that the PFN entry corresponds to a valid, active physical page */ if((PageFrameIndex <= HighestPhysicalPage) && (MM::Pte::AddressValid(Pfn)) && (MM::Pte::AddressValid(EndAddress)) && (Pfn->u3.e1.PageLocation == ActiveAndValid)) { /* Initialize the PFN entry for this page table page */ MM::Paging::SetPte(&Pfn->OriginalPte, MM::Paging::GetPte(PointerPte)); Pfn->PteAddress = PointerPte; Pfn->u1.WsIndex = 0; Pfn->u2.ShareCount++; Pfn->u3.e1.CacheAttribute = PfnNonCached; Pfn->u3.e1.PageLocation = ActiveAndValid; Pfn->u3.e2.ReferenceCount = 1; Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress(PointerPte)); } /* Increment the share count of the parent page table that contains the mapping */ PointerPde = MM::Paging::GetPdeAddress(MM::Paging::GetPteVirtualAddress(PointerPte)); Pfn = GetPfnEntry(MM::Paging::GetPageFrameNumber(PointerPde)); Pfn->u2.ShareCount++; } /** * Links a PFN entry to its corresponding PTE and ensures the page table that contains the PTE is resident in memory. * * @param PageFrameIndex * Supplies the index into the PFN database for the page being initialized. * * @param PointerPte * Supplies the pointer to the PTE which maps the physical page. * * @param ParentFrame * Supplies the page frame number of the page table that contains the PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::LinkPfnWithParent(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN PFN_NUMBER ParentFrame) { PMMMEMORY_LAYOUT MemoryLayout; PMMPFN Pfn; /* Get the memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Point the PFN to its PTE */ Pfn = &((PMMPFN)MemoryLayout->PfnDatabase)[PageFrameIndex]; Pfn->PteAddress = PointerPte; /* Initialize the PTE */ MM::Paging::SetPte(&Pfn->OriginalPte, 0, MM_PTE_GUARDED); /* Initialize the PFN entry */ Pfn->u2.ShareCount++; Pfn->u3.e1.CacheAttribute = PfnCached; Pfn->u3.e1.Modified = TRUE; Pfn->u3.e1.PageLocation = ActiveAndValid; Pfn->u3.e2.ReferenceCount++; Pfn->u4.InPageError = FALSE; /* Check if parent PTE frame exists */ if(ParentFrame) { /* Link the page table to its parent */ Pfn->u4.PteFrame = ParentFrame; /* Get the PFN entry for parent PTE and increment share count */ Pfn = &((PMMPFN)MemoryLayout->PfnDatabase)[ParentFrame]; Pfn->u2.ShareCount++; } } /** * Links a page to the beginning of the appropriate standby or ROM list. * * @param PageFrameIndex * The Page Frame Number (PFN) of the page to link. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID MM::Pfn::LinkStandbyPage(IN PFN_NUMBER PageFrameIndex) { PMMPFN AdjacentPageFrame, CurrentPageFrame; PMMMEMORY_LAYOUT MemoryLayout; PFN_NUMBER Flink; /* Get the memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Get the PFN database entry for the target page */ CurrentPageFrame = &((PMMPFN)MemoryLayout->PfnDatabase)[PageFrameIndex]; /* Check if the page is part of a ROM image */ if(CurrentPageFrame->u3.e1.Rom == 1) { /* Increment the total number of ROM pages */ RomPagesList.Total++; /* If the ROM list is not empty, link the new page */ if(RomPagesList.Blink != (ULONG_PTR)-1) { /* Update the old tail to point to the new page */ AdjacentPageFrame = &((PMMPFN)MemoryLayout->PfnDatabase)[RomPagesList.Blink]; AdjacentPageFrame->u1.Flink = PageFrameIndex; } else { /* Otherwise, this page is now the head of the list */ RomPagesList.Flink = PageFrameIndex; } /* Set the new page as the tail and update its links */ RomPagesList.Blink = PageFrameIndex; CurrentPageFrame->u1.Flink = (ULONG_PTR)-1; CurrentPageFrame->u2.Blink = RomPagesList.Blink; CurrentPageFrame->u3.e1.PageLocation = StandbyPageList; /* ROM pages require no further processing */ return; } /* Increment the count of pages on the standby list */ StandbyPagesList.Total++; /* Save the old head and set the current page as the new head */ Flink = StandbyPagesList.Flink; StandbyPagesList.Flink = PageFrameIndex; /* Point the new head to the old one, marking it as the list front */ CurrentPageFrame->u1.Flink = Flink; CurrentPageFrame->u2.Blink = MAXULONG_PTR; /* If the ROM list is not empty, link the new page */ if(Flink != MAXULONG_PTR) { /* Update the old head to point to the new page */ AdjacentPageFrame = &((PMMPFN)MemoryLayout->PfnDatabase)[Flink]; AdjacentPageFrame->u2.Blink = PageFrameIndex; } else { /* Otherwise, this page is now the tail of the list */ StandbyPagesList.Blink = PageFrameIndex; } /* Update the page's location to the standby list */ CurrentPageFrame->u3.e1.PageLocation = StandbyPageList; /* Increment number of available pages */ IncrementAvailablePages(); } /** * Processes a memory descriptor and initializes the corresponding PFN database entries. * * @param BasePage * The starting physical page number of the memory run. * * @param PageCount * The number of pages in the memory run. * * @param MemoryType * The type of memory as reported by the bootloader (e.g., free, ROM, in-use). * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, IN PFN_NUMBER PageCount, IN LOADER_MEMORY_TYPE MemoryType) { PVOID VirtualAddress, VirtualRangeStart, VirtualRangeEnd; PFN_NUMBER PageNumber; PMMPDE PointerPde; PMMPFN Pfn; /* Check if the memory descriptor describes a free memory region */ if(MM::Manager::VerifyMemoryTypeFree(MemoryType)) { /* Iterate over each page in this free memory run */ for(PageNumber = 0; PageNumber < PageCount; PageNumber++) { /* Get the PFN entry for the current page and ensure it is not referenced */ Pfn = GetPfnEntry(BasePage + PageNumber); if(Pfn->u3.e2.ReferenceCount == 0) { /* Add the page to the free list to make it available for allocation */ LinkFreePage(BasePage + PageNumber); } } } else { /* Calculate the virtual address range for this physical memory region */ VirtualRangeStart = (PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT)); VirtualRangeEnd = (PVOID)(KSEG0_BASE + ((BasePage + PageCount) << MM_PAGE_SHIFT)); /* Handle all other (non-free) memory types */ switch(MemoryType) { case LoaderBad: /* This memory is marked as bad and should not be used */ for(PageNumber = 0; PageNumber < PageCount; PageNumber++) { /* Link the page to the bad pages list */ LinkPage(&BadPagesList, BasePage + PageNumber); } break; case LoaderXIPRom: /* Get the page directory entry for the current page */ PointerPde = MM::Paging::GetPdeAddress(VirtualRangeStart); /* Initialize the page directory entries covering this memory range */ InitializePageDirectory(PointerPde, MM::Paging::GetPdeAddress(VirtualRangeEnd)); /* This memory range contains Read-Only Memory (ROM) */ for(PageNumber = 0; PageNumber < PageCount; PageNumber++) { /* Get the PFN entry for the current ROM page */ Pfn = GetPfnEntry(BasePage + PageNumber); /* Ensure that the page is not already in-use */ if(Pfn->u3.e2.ReferenceCount == 0) { /* Calculate the virtual address for this page */ VirtualAddress = (PVOID)(KSEG0_BASE + ((BasePage + PageNumber) << MM_PAGE_SHIFT)); PointerPde = MM::Paging::GetPdeAddress(VirtualAddress); /* Initialize the PFN entry to represent a ROM page */ Pfn->PteAddress = MM::Paging::GetPteAddress(VirtualAddress); Pfn->u1.Flink = 0; Pfn->u2.ShareCount = 0; Pfn->u3.e1.CacheAttribute = PfnCached; Pfn->u3.e1.PageLocation = 0; Pfn->u3.e1.PrototypePte = 1; Pfn->u3.e1.Rom = 1; Pfn->u3.e2.ReferenceCount = 0; Pfn->u4.InPageError = 0; Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(PointerPde); } } break; default: /* Get the page directory entry for the current page */ PointerPde = MM::Paging::GetPdeAddress(VirtualRangeStart); /* Initialize the page directory entries covering this memory range */ InitializePageDirectory(PointerPde, MM::Paging::GetPdeAddress(VirtualRangeEnd)); /* All other types are considered in-use (ie, by the kernel, ACPI, etc) */ for(PageNumber = 0; PageNumber < PageCount; PageNumber++) { /* Get the PFN entry for the current in-use page */ Pfn = GetPfnEntry(BasePage + PageNumber); /* Ensure that the page is not already in-use */ if(Pfn->u3.e2.ReferenceCount == 0) { /* Calculate the virtual address for this page */ VirtualAddress = (PVOID)(KSEG0_BASE + ((BasePage + PageNumber) << MM_PAGE_SHIFT)); PointerPde = MM::Paging::GetPdeAddress(VirtualAddress); /* Initialize the PFN entry to represent an in-use page and prevent it from being allocated */ Pfn->PteAddress = MM::Paging::GetPteAddress(VirtualAddress); Pfn->u2.ShareCount++; Pfn->u3.e1.CacheAttribute = PfnCached; Pfn->u3.e1.PageLocation = ActiveAndValid; Pfn->u3.e2.ReferenceCount = 1; Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(PointerPde); } } break; } } } /** * Scans memory descriptors provided by the boot loader. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pfn::ScanMemoryDescriptors(VOID) { PLIST_ENTRY LoaderMemoryDescriptors, MemoryMappings; PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor; PFN_NUMBER FreePages; /* Initialize the highest and lowest physical page numbers */ HighestPhysicalPage = (ULONG_PTR)0; LowestPhysicalPage = (ULONG_PTR)~0; /* Initially, set number of free pages to 0 */ FreePages = 0; /* Get the list head of memory descriptors */ LoaderMemoryDescriptors = KE::BootInformation::GetMemoryDescriptors(); /* Iterate through the memory descriptors */ MemoryMappings = LoaderMemoryDescriptors->Flink; while(MemoryMappings != LoaderMemoryDescriptors) { /* Get the memory descriptor */ MemoryDescriptor = CONTAIN_RECORD(MemoryMappings, LOADER_MEMORY_DESCRIPTOR, ListEntry); /* Skip invisible or hardware cached memory regions */ if(MM::Manager::VerifyMemoryTypeInvisible(MemoryDescriptor->MemoryType) || (MemoryDescriptor->MemoryType == LoaderHardwareCachedMemory)) { /* Move to the next descriptor and skip further processing */ MemoryMappings = MemoryMappings->Flink; continue; } /* Count the number of physical pages, excluding bad memory */ if(MemoryDescriptor->MemoryType != LoaderBad) { /* Add the pages from this descriptor to the total count */ NumberOfPhysicalPages += MemoryDescriptor->PageCount; } /* Check if this physical page is the lowest one yet */ if(MemoryDescriptor->BasePage < LowestPhysicalPage) { /* Update the lowest physical page number found so far */ LowestPhysicalPage = MemoryDescriptor->BasePage; } /* Check if this physical page is the highest one yet */ if((MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) > HighestPhysicalPage) { /* Update the highest physical page number found so far */ HighestPhysicalPage = (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) - 1; } /* Identify the largest block of free memory */ if(MM::Manager::VerifyMemoryTypeFree(MemoryDescriptor->MemoryType)) { /* Check if this free memory block is the largest one yet */ if(MemoryDescriptor->PageCount >= FreePages) { /* Update the largest free block size and save the descriptor */ FreePages = MemoryDescriptor->PageCount; FreeDescriptor = MemoryDescriptor; } } /* Get next memory descriptor */ MemoryMappings = MemoryMappings->Flink; } /* Ensure a free memory descriptor was found */ if(!FreeDescriptor) { /* No free memory available to bootstrap the system */ KE::Crash::Panic(0x7D, LowestPhysicalPage, HighestPhysicalPage, FreePages, 0x1); } /* Save a copy of the original free descriptor before it gets modified */ RTL::Memory::CopyMemory(&OriginalFreeDescriptor, FreeDescriptor, sizeof(LOADER_MEMORY_DESCRIPTOR)); } /** * Unlinks a physical page from its corresponding list. * * @param PageIndex * The Page Frame Number (PFN) of the page to unlink. * * @param Color * The color of the page, used to find the correct colored list. * * @return This routine returns the PFN of the page that was unlinked. */ XTAPI PFN_NUMBER MM::Pfn::UnlinkFreePage(IN PFN_NUMBER PageFrameIndex, IN ULONG Color) { PMMPFN Pfn; PMMPFNLIST PfnList; MMPAGELISTS PageList; ULONG NodeColor; PMMCOLOR_TABLES ColorTable; PFN_NUMBER NextPage, PrevPage; /* Get the PFN database entry for the target page */ Pfn = GetPfnEntry(PageFrameIndex); /* Identify which list the page belongs to (FreePageList or ZeroedPageList) */ PfnList = PageLocationList[Pfn->u3.e1.PageLocation]; PageList = PfnList->ListName; /* Update the forward link of the previous page */ if(Pfn->u2.Blink != MAXULONG_PTR) { /* The page is not the head of the list; update the previous page's Flink */ GetPfnEntry(Pfn->u2.Blink)->u1.Flink = Pfn->u1.Flink; } else { /* This is the first page in the list; update the list head's Flink */ PfnList->Flink = Pfn->u1.Flink; } /* Update the backward link of the next page */ if(Pfn->u1.Flink != MAXULONG_PTR) { /* The page is not the tail of the list; update the next page's Blink */ GetPfnEntry(Pfn->u1.Flink)->u2.Blink = Pfn->u2.Blink; } else { /* This is the last page in the list; update the list head's Blink */ PfnList->Blink = Pfn->u2.Blink; } /* Get the first page on the color list */ ColorTable = MM::Colors::GetFreePages(PageList, Color); NodeColor = Pfn->u3.e1.PageColor; PrevPage = Pfn->u4.PteFrame; NextPage = MM::Paging::GetPte(&Pfn->OriginalPte); /* Decrement the count of pages for this specific color and total page count for this list */ ColorTable->Count--; PfnList->Total--; /* Update the forward link of the previous colored page */ if(PrevPage != MM_PFN_PTE_FRAME) { /* This is not the first page; update the previous page's Flink */ MM::Paging::SetPte(&GetPfnEntry(PrevPage)->OriginalPte, NextPage); } else { /* This was the first page; update the color table's Flink */ ColorTable->Flink = NextPage; } /* Update the backward link of the next colored page */ if (NextPage != MAXULONG_PTR) { /* This is not the last page; update the next page's Blink */ GetPfnEntry(NextPage)->u4.PteFrame = PrevPage; } else { /* This was the last page; update the color table's Blink */ ColorTable->Blink = (PVOID)PrevPage; } /* Clear the list pointers and flags, but preserve the color and cache attributes */ Pfn->u1.Flink = 0; Pfn->u2.Blink = 0; Pfn->u3.e1.CacheAttribute = PfnNotMapped; Pfn->u3.e1.PageColor = NodeColor; Pfn->u3.e2.ShortFlags = 0; /* Decrement the global count of available pages */ DecrementAvailablePages(); /* Return the page that was just unlinked */ return PageFrameIndex; } ================================================ FILE: xtoskrnl/mm/pool.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/pool.cc * DESCRIPTION: Memory Manager pool manager * DEVELOPERS: Aiken Harris */ #include /** * Decodes an obfuscated doubly-linked pool list pointer. * * @param Link * Supplies the encoded list entry pointer to be decoded. * * @return This routine returns the valid, properly aligned list entry pointer. * * @since XT 1.0 */ XTAPI PLIST_ENTRY MM::Pool::DecodePoolLink(IN PLIST_ENTRY PoolLink) { /* XOR the obfuscated pointer with the global pool cookie to reveal the true address */ return (PLIST_ENTRY)((ULONG_PTR)PoolLink ^ PoolSecureCookie); } /** * Determines the pool type for a given memory address. * * @param VirtualAddress * Supplies a virtual address to determine the pool type for. * * @return This routine returns the determined pool type for the specified address. * * @since XT 1.0 */ XTAPI MMPOOL_TYPE MM::Pool::DeterminePoolType(IN PVOID VirtualAddress) { PMMMEMORY_LAYOUT MemoryLayout; /* Retrieve the memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Evaluate the virtual address against known pool boundaries */ if((VirtualAddress >= MemoryLayout->NonPagedPoolStart) && (VirtualAddress <= MemoryLayout->NonPagedPoolEnd)) { /* Address belongs to the non-paged pool */ return NonPagedPool; } else if((VirtualAddress >= MemoryLayout->NonPagedExpansionPoolStart) && (VirtualAddress <= MemoryLayout->NonPagedExpansionPoolEnd)) { /* Address belongs to the non-paged expansion pool */ return NonPagedPool; } else if((VirtualAddress >= MemoryLayout->PagedPoolStart) && (VirtualAddress <= MemoryLayout->PagedPoolEnd)) { /* Address belongs to the paged pool */ return PagedPool; } /* Address does not belong to any known pool, kernel panic */ KE::Crash::Panic(0xC2, 0x42, (ULONG_PTR)VirtualAddress, 0, 0); /* Return an invalid pool type to satisfy the compiler */ return (MMPOOL_TYPE)-1; } /** * Encodes a doubly-linked pool list pointer to mitigate pool corruption. * * @param Link * Supplies the raw list entry pointer to be encoded. * * @return This routine returns the obfuscated list entry pointer. * * @since XT 1.0 */ XTAPI PLIST_ENTRY MM::Pool::EncodePoolLink(IN PLIST_ENTRY PoolLink) { /* XOR the raw pointer with the global pool cookie to securely obfuscate it */ return (PLIST_ENTRY)((ULONG_PTR)PoolLink ^ PoolSecureCookie); } /** * Calculates the address of a pool block at a specific relative index. * * @param Header * Supplies a pointer to the base pool header. * * @param Index * Supplies the block index offset. This value can be negative to traverse backwards. * * @return This routine returns a pointer to the calculated pool header. * * @since XT 1.0 */ XTAPI PPOOL_HEADER MM::Pool::GetPoolBlock(IN PPOOL_HEADER Header, IN SSIZE_T Index) { /* The destination block is located by advancing the base address by the specified index */ return (PPOOL_HEADER)((ULONG_PTR)Header + (Index * MM_POOL_BLOCK_SIZE)); } /** * Retrieves the pool header associated with a given pool memory address. * * @param Memory * Supplies a pointer to the allocated memory region of a pool block. * * @return This routine returns a pointer to the originating pool header. * * @since XT 1.0 */ XTAPI PPOOL_HEADER MM::Pool::GetPoolEntry(IN PVOID Memory) { /* The structural header logically precedes the allocated memory region */ return (PPOOL_HEADER)((ULONG_PTR)Memory - sizeof(POOL_HEADER)); } /** * Resolves the list entry structure embedded within a free pool block. * * @param Header * Supplies a pointer to the pool header. * * @return This routine returns a pointer to the list entry directly following the header. * * @since XT 1.0 */ XTAPI PLIST_ENTRY MM::Pool::GetPoolFreeBlock(IN PPOOL_HEADER Header) { /* Return the list entry pointer */ return (PLIST_ENTRY)((ULONG_PTR)Header + sizeof(POOL_HEADER)); } /** * Retrieves a pointer to the adjacent contiguous pool block following the specified header. * * @param Header * Supplies a pointer to the current pool header. * * @return This routine returns a pointer to the next pool header in memory. * * @since XT 1.0 */ XTAPI PPOOL_HEADER MM::Pool::GetPoolNextBlock(IN PPOOL_HEADER Header) { /* The adjacent forward header is located exactly 'BlockSize' units ahead of the current block */ return (PPOOL_HEADER)((ULONG_PTR)Header + (Header->BlockSize * MM_POOL_BLOCK_SIZE)); } /** * Retrieves a pointer to the adjacent contiguous pool block preceding the specified header. * * @param Header * Supplies a pointer to the current pool header. * * @return This routine returns a pointer to the previous pool header in memory. * * @since XT 1.0 */ XTAPI PPOOL_HEADER MM::Pool::GetPoolPreviousBlock(IN PPOOL_HEADER Header) { /* The adjacent backward header is located exactly 'PreviousSize' units behind the current block */ return (PPOOL_HEADER)((ULONG_PTR)Header - (Header->PreviousSize * MM_POOL_BLOCK_SIZE)); } /** * Initializes the non-paged pool for memory allocator. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::InitializeNonPagedPool(VOID) { PMMFREE_POOL_ENTRY FreePage, SetupPage; PMMMEMORY_LAYOUT MemoryLayout; ULONG Index; /* Retrieve memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); /* Map PTEs for the non-paged pool */ MapNonPagedPool(); /* Iterate over the free page list heads */ for(Index = 0; Index < MM_MAX_FREE_PAGE_LIST_HEADS; Index++) { /* Initialize a free page list head */ RTL::LinkedList::InitializeListHead(&NonPagedPoolFreeList[Index]); } /* Take the first free page from the pool and set its size */ FreePage = (PMMFREE_POOL_ENTRY)MemoryLayout->NonPagedPoolStart; FreePage->Size = MemoryLayout->NonPagedPoolSize; /* Take number of pages in the pool */ Index = (ULONG)(MemoryLayout->NonPagedPoolSize - 1); if(Index >= MM_MAX_FREE_PAGE_LIST_HEADS) { /* Number of pages exceeds the number of free page list heads */ Index = MM_MAX_FREE_PAGE_LIST_HEADS - 1; } /* Insert the first free page into the free page list */ RTL::LinkedList::InsertHeadList(&NonPagedPoolFreeList[Index], &FreePage->List); /* Create a free page for each page in the pool */ SetupPage = FreePage; for(Index = 0; Index < MemoryLayout->NonPagedPoolSize; Index++) { /* Initialize the owner for each page */ SetupPage->Owner = FreePage; SetupPage = (PMMFREE_POOL_ENTRY)((ULONG_PTR)SetupPage + MM_PAGE_SIZE); } /* Store first and last allocated non-paged pool page */ NonPagedPoolFrameStart = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress(MemoryLayout->NonPagedPoolStart)); NonPagedPoolFrameEnd = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress(MemoryLayout->NonPagedPoolEnd)); /* Initialize system PTE pool for the non-paged expansion pool */ Pte::InitializeSystemPtePool(Paging::GetNextPte(Paging::GetPteAddress(MemoryLayout->NonPagedExpansionPoolStart)), MemoryLayout->NonPagedExpansionPoolSize - 2, NonPagedPoolExpansion); /* Store non-paged pool descriptor in the pool vector and initialize it */ PoolVector[NonPagedPool] = &NonPagedPoolDescriptor; InitializePoolDescriptor(PoolVector[NonPagedPool], NonPagedPool, 0, 0, NULLPTR); } /** * Initializes the non-paged pool for memory allocator. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::InitializePagedPool(VOID) { UNIMPLEMENTED; } /** * Initializes a pool descriptor used by the memory manager. * * @param Descriptor * Supplies a pointer to the pool descriptor structure to be initialized. * * @param PoolType * Specifies the type of memory pool that will be managed by the descriptor. * * @param Index * Supplies the zero-based index of the descriptor within the pool vector. * * @param Threshold * Specifies the allocation threshold that dictates when the pool should expand. * * @param LockAddress * Supplies a pointer to the synchronization primitive that will serialize access to this descriptor. * * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::InitializePoolDescriptor(IN PPOOL_DESCRIPTOR Descriptor, IN MMPOOL_TYPE PoolType, IN ULONG Index, IN ULONG Threshold, IN PVOID LockAddress) { PLIST_ENTRY LastEntry, ListEntry; /* Populate the core attributes of the descriptor */ Descriptor->LockAddress = LockAddress; Descriptor->PoolIndex = Index; Descriptor->PoolType = PoolType; Descriptor->Threshold = Threshold; /* Clear the deferred free list */ Descriptor->PendingFrees = NULLPTR; Descriptor->PendingFreeDepth = 0; /* Zero out the runtime accounting and statistical tracking counters */ Descriptor->RunningAllocations = 0; Descriptor->RunningFrees = 0; Descriptor->TotalBigAllocations = 0; Descriptor->TotalBytes = 0; Descriptor->TotalPages = 0; /* Establish the iteration boundaries */ ListEntry = Descriptor->ListHeads; LastEntry = ListEntry + MM_POOL_LISTS_PER_PAGE; /* Traverse and initialize all block list heads */ while(ListEntry < LastEntry) { /* Initialize the empty list head */ InitializePoolListHead(ListEntry); ListEntry++; } } /** * Initializes a doubly-linked pool list head with encoded pointers. * * @param ListHead * Supplies a pointer to the pool list head that is to be initialized. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::InitializePoolListHead(IN PLIST_ENTRY ListHead) { PLIST_ENTRY ListEntry; /* Obfuscate the list head address and establish the empty circular linkage */ ListEntry = EncodePoolLink(ListHead); ListHead->Flink = ListEntry; ListHead->Blink = ListEntry; } /** * Initializes the memory pool security mechanisms. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::InitializePoolSecurity(VOID) { UNIMPLEMENTED; /* Initialize the global pool cookie using a hard-coded value */ PoolSecureCookie = 0xDEADC0DE; } /** * Inserts a pool entry at the head of a doubly-linked pool list. * * @param ListHead * Supplies a pointer to the head of the pool list. * * @param Entry * Supplies a pointer to the pool list entry to be inserted. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::InsertPoolHeadList(IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry) { PLIST_ENTRY Flink; /* Validate the pool list structure */ VerifyPoolLinks(ListHead); /* Resolve the current forward link of the list head */ Flink = DecodePoolLink(ListHead->Flink); /* Securely insert the new entry at the beginning of the pool list */ Entry->Blink = EncodePoolLink(ListHead); Entry->Flink = EncodePoolLink(Flink); Flink->Blink = EncodePoolLink(Entry); ListHead->Flink = EncodePoolLink(Entry); /* Re-validate the pool list structure */ VerifyPoolLinks(ListHead); } /** * Inserts a pool entry at the tail of a doubly-linked pool list. * * @param ListHead * Supplies a pointer to the head of the pool list. * * @param Entry * Supplies a pointer to the pool list entry to be inserted. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::InsertPoolTailList(IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry) { PLIST_ENTRY Blink; /* Validate the pool list structure */ VerifyPoolLinks(ListHead); /* Securely link the new entry at the end of the pool list */ Blink = DecodePoolLink(ListHead->Blink); Blink->Flink = EncodePoolLink(Entry); Entry->Blink = EncodePoolLink(Blink); Entry->Flink = EncodePoolLink(ListHead); ListHead->Blink = EncodePoolLink(Entry); /* Re-validate the pool list structure */ VerifyPoolLinks(ListHead); } /** * Determines whether a given doubly-linked pool list is empty. * * @param ListHead * Supplies a pointer to the head of the pool list to be evaluated. * * @return This routine returns TRUE if the pool list is empty, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Pool::PoolListEmpty(IN PLIST_ENTRY ListHead) { /* Evaluate whether the pool list contains no valid entries */ return (DecodePoolLink(ListHead->Flink) == ListHead); } /** * Removes a specific pool entry from a doubly-linked pool list. * * @param Entry * Supplies a pointer to the pool list entry to be removed. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::RemovePoolEntryList(IN PLIST_ENTRY Entry) { PLIST_ENTRY Blink, Flink; /* Resolve the adjacent forward and backward links */ Blink = DecodePoolLink(Entry->Blink); Flink = DecodePoolLink(Entry->Flink); /* Securely link the adjacent nodes together */ Blink->Flink = EncodePoolLink(Flink); Flink->Blink = EncodePoolLink(Blink); } /** * Removes the first entry from a doubly-linked pool list. * * @param ListHead * Supplies a pointer to the head of the pool list. * * @return This routine returns a pointer to the removed pool list entry. * * @since XT 1.0 */ XTAPI PLIST_ENTRY MM::Pool::RemovePoolHeadList(IN PLIST_ENTRY ListHead) { PLIST_ENTRY Entry, Flink; /* Securely unlink the first entry from the pool list */ Entry = DecodePoolLink(ListHead->Flink); Flink = DecodePoolLink(Entry->Flink); Flink->Blink = EncodePoolLink(ListHead); ListHead->Flink = EncodePoolLink(Flink); /* Return the removed pool list entry */ return Entry; } /** * Removes the last entry from a doubly-linked pool list. * * @param ListHead * Supplies a pointer to the head of the pool list. * * @return This routine returns a pointer to the removed pool list entry. * * @since XT 1.0 */ PLIST_ENTRY XTAPI MM::Pool::RemovePoolTailList(IN PLIST_ENTRY ListHead) { PLIST_ENTRY Blink, Entry; /* Securely unlink the last entry from the pool list */ Entry = DecodePoolLink(ListHead->Blink); Blink = DecodePoolLink(Entry->Blink); Blink->Flink = EncodePoolLink(ListHead); ListHead->Blink = EncodePoolLink(Blink); /* Return the removed pool list entry */ return Entry; } /** * Verifies the structural integrity of all pool blocks residing on a specific page. * * @param Block * Supplies a pointer to the specific pool block. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::VerifyPoolBlocks(IN PVOID Block) { PPOOL_HEADER Entry; BOOLEAN FoundBlock; SIZE_T Size; /* Initialize tracking variables */ FoundBlock = FALSE; Size = 0; /* Resolve the first pool header */ Entry = (PPOOL_HEADER)PAGE_ALIGN(Block); /* Iterate through all contiguous pool allocations */ do { /* Validate the current pool header */ VerifyPoolHeader(Entry); /* Check if the current header corresponds to the target block */ if(Entry == Block) { /* Mark the block as found */ FoundBlock = TRUE; } /* Accumulate the total block size and advance to the next entry */ Size += Entry->BlockSize; Entry = GetPoolNextBlock(Entry); } while((Size < (MM_PAGE_SIZE / MM_POOL_BLOCK_SIZE)) && (PAGE_ALIGN(Entry) != Entry)); /* Ensure the block was found and the total size is aligned with the page */ if(!FoundBlock || (PAGE_ALIGN(Entry) != Entry) || (Size != (MM_PAGE_SIZE / MM_POOL_BLOCK_SIZE))) { /* Pool blocks corruption detected, kernel panic */ KE::Crash::Panic(0x19, 10, (ULONG_PTR)Block, (ULONG_PTR)Entry, FoundBlock); } } /** * Verifies the structural and spatial invariants of a specific pool header. * * @param Entry * Supplies a pointer to the pool header to be verified. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::VerifyPoolHeader(IN PPOOL_HEADER Entry) { PPOOL_HEADER PreviousEntry, NextEntry; /* Verify that the current block header is valid */ if(!Entry->BlockSize) { /* Invalid block header size, kernel panic */ KE::Crash::Panic(0x19, 8, (ULONG_PTR)Entry->PreviousSize, Entry->BlockSize, (ULONG_PTR)Entry); } /* Verify that the previous block header is valid */ if(Entry->PreviousSize) { /* Resolve the previous block header */ PreviousEntry = GetPoolPreviousBlock(Entry); /* Check if both adjacent blocks are within the same memory page */ if(PAGE_ALIGN(Entry) != PAGE_ALIGN(PreviousEntry)) { /* Adjacent blocks are not on the same page, kernel panic */ KE::Crash::Panic(0x19, 6, (ULONG_PTR)PreviousEntry, (ULONG_PTR)PAGE_ALIGN(Entry), (ULONG_PTR)Entry); } /* Check the actual size of the previous block */ if(PreviousEntry->BlockSize != Entry->PreviousSize) { /* Block size mismatch, kernel panic */ KE::Crash::Panic(0x19, 5, (ULONG_PTR)PreviousEntry, (ULONG_PTR)Entry->PreviousSize, (ULONG_PTR)Entry); } } else if(PAGE_ALIGN(Entry) != Entry) { /* Not aligned to a page boundary, kernel panic */ KE::Crash::Panic(0x19, 7, 0, (ULONG_PTR)PAGE_ALIGN(Entry), (ULONG_PTR)Entry); } /* Resolve the next block header */ NextEntry = GetPoolNextBlock(Entry); /* Verify the next block header */ if(PAGE_ALIGN(NextEntry) != NextEntry) { /* Check if both adjacent blocks are within the same memory page */ if(PAGE_ALIGN(Entry) != PAGE_ALIGN(NextEntry)) { /* Adjacent blocks are not on the same page, kernel panic */ KE::Crash::Panic(0x19, 9, (ULONG_PTR)NextEntry, (ULONG_PTR)PAGE_ALIGN(Entry), (ULONG_PTR)Entry); } /* Check the previous block size */ if(NextEntry->PreviousSize != Entry->BlockSize) { /* Block size mismatch, kernel panic */ KE::Crash::Panic(0x19, 5, (ULONG_PTR)NextEntry, NextEntry->PreviousSize, (ULONG_PTR)Entry); } } } /** * Validates the structural integrity of a doubly-linked pool list. * * @param ListHead * Supplies a pointer to the pool list head that is to be validated. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::VerifyPoolLinks(IN PLIST_ENTRY ListHead) { /* Validate the doubly-linked list invariants */ if((DecodePoolLink(DecodePoolLink(ListHead->Blink)->Flink) != ListHead) || (DecodePoolLink(DecodePoolLink(ListHead->Flink)->Blink) != ListHead)) { /* Pool corruption detected, raise kernel panic */ KE::Crash::Panic(0x19, 3, (ULONG_PTR)ListHead, (ULONG_PTR)DecodePoolLink(DecodePoolLink(ListHead->Blink)->Flink), (ULONG_PTR)DecodePoolLink(DecodePoolLink(ListHead->Flink)->Blink)); } } /** * Validates the run level for the specified pool. If the run level is invalid, the kernel panics. * * @param PoolType * Supplies the pool type. * * @param Bytes * Supplies the size of the allocation. * * @param Entry * Supplies a pointer to the allocation entry. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pool::VerifyRunLevel(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, IN PVOID Entry) { KRUNLEVEL RunLevel; /* Get current run level */ RunLevel = KE::RunLevel::GetCurrentRunLevel(); /* Validate run level */ if((PoolType & MM_POOL_TYPE_MASK) == PagedPool) { /* Paged pool runs up to APC level */ if(RunLevel <= APC_LEVEL) { /* Run level is valid */ return; } } else { /* Non-paged pool runs up to DISPATCH_LEVEL */ if(RunLevel <= DISPATCH_LEVEL) { /* Run level is valid */ return; } } /* Invalid run level for specified pool, raise kernel panic */ KE::Crash::Panic(0xC2, (Entry ? MM_POOL_INVALID_FREE_RUNLEVEL : MM_POOL_INVALID_ALLOC_RUNLEVEL), RunLevel, PoolType, (Entry ? (ULONG_PTR)Entry : Bytes)); } ================================================ FILE: xtoskrnl/mm/pte.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/pte.cc * DESCRIPTION: Page Table Entry (PTE) support * DEVELOPERS: Aiken Harris */ #include /** * Finds a free cluster of system PTEs that can satisfy a given size. * * @param NumberOfPtes * The number of contiguous PTEs required. * * @param SystemPtePoolType * Specifies the system PTE pool to search within. * * @param FoundCluster * On success, receives a pointer to the first PTE of the found cluster. * * @param PreviousClusterNode * On success, receives a pointer to the list node that precedes the found cluster. * * @return This routine returns TRUE if a suitable cluster was found, FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN MM::Pte::FindFreeCluster(IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, OUT PMMPTE *FoundCluster, OUT PMMPTE *PreviousClusterNode) { PMMPTE CurrentCluster; PMMPTE PreviousNode = &FirstSystemFreePte[SystemPtePoolType]; ULONG ClusterSize; /* Find a free PTE cluster large enough for the request */ while(MM::Paging::GetNextEntry(PreviousNode) != MAXULONG) { /* Retrieve the cluster and its size */ CurrentCluster = MM::Paging::AdvancePte(SystemPteBase, MM::Paging::GetNextEntry(PreviousNode)); ClusterSize = GetClusterSize(CurrentCluster); /* Check if this cluster is large enough */ if(NumberOfPtes <= ClusterSize) { /* Found a suitable cluster */ *FoundCluster = CurrentCluster; *PreviousClusterNode = PreviousNode; return TRUE; } /* This cluster is too small, check the next one */ PreviousNode = CurrentCluster; } /* No suitable cluster was found */ return FALSE; } /** * Decodes and returns the size of a free PTE cluster. * * @param Pte * Supplies a pointer to the first PTE of the free cluster to inspect. * * @return This routine returns the total number of contiguous PTEs in the free cluster. * * @since XT 1.0 */ XTAPI ULONG MM::Pte::GetClusterSize(IN PMMPTE Pte) { /* A special flag in the first PTE indicates a free cluster of size one */ if(MM::Paging::GetOneEntry(Pte)) { /* Flag is set, so the cluster size is 1 by definition */ return 1; } /* For larger clusters, the size is encoded in the second PTE of the block */ Pte = MM::Paging::GetNextPte(Pte); return MM::Paging::GetNextEntry(Pte); } /** * Calculates the number of Page Table Entries (PTEs) that fit within a single page. * * @return This routine returns the number of PTEs per page. * * @since XT 1.0 */ XTAPI PFN_COUNT MM::Pte::GetPtesPerPage(VOID) { /* Calculate and return the number of PTEs per page */ return MM_PAGE_SIZE / MM::Paging::GetPteSize(); } /** * Returns a pointer to the valid PTE. * * @return This routine returns a pointer to the valid PTE. * * @since XT 1.0 */ XTAPI PMMPTE MM::Pte::GetValidPte() { /* Return a pointer to the valid PTE */ return &ValidPte; } /** * Initializes the system's PTE. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pte::InitializeSystemPte(VOID) { /* Initialize the PTE template */ MM::Paging::SetPte(&ValidPte, MM_PTE_VALID | MM_PTE_EXECUTE_READWRITE | MM_PTE_DIRTY | MM_PTE_ACCESSED); } /** * Formats a range of PTEs into a freelist-based pool for system allocations. * * @param StartingPte * Supplies a pointer to the start of the PTE range to be formatted. * * @param NumberOfPtes * Supplies the total number of PTEs in the contiguous range. * * @param PoolType * The system PTE pool type that this range will be used for. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pte::InitializeSystemPtePool(IN PMMPTE StartingPte, IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE PoolType) { /* Set the system PTE base address */ SystemPteBase = GetSystemPteBaseAddress(); /* Record the boundaries of this new PTE pool */ SystemPtesStart[PoolType] = StartingPte; SystemPtesEnd[PoolType] = MM::Paging::AdvancePte(StartingPte, NumberOfPtes - 1); /* Zero the memory for the new PTE pool before use */ RTL::Memory::ZeroMemory(StartingPte, NumberOfPtes * MM::Paging::GetPteSize()); /* Build the free list head to point to the start of the pool */ MM::Paging::SetNextEntry(StartingPte, MAXULONG); MM::Paging::ClearPte(&FirstSystemFreePte[PoolType]); MM::Paging::SetNextEntry(&FirstSystemFreePte[PoolType], MM::Paging::GetPteDistance(StartingPte, SystemPteBase)); /* Use the second PTE slot to store the total size of this pool */ StartingPte = MM::Paging::GetNextPte(StartingPte); MM::Paging::ClearPte(StartingPte); MM::Paging::SetNextEntry(StartingPte, NumberOfPtes); /* Record the total number of free PTEs in this pool */ TotalSystemFreePtes[PoolType] = NumberOfPtes; } /** * Sets up the entire system PTE address space. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pte::InitializeSystemPteSpace(VOID) { PMMPTE PointerPte; PMMPTE FirstZeroingPte; PMMMEMORY_LAYOUT MemoryLayout; ULONGLONG NonPagedSystemPoolEnd; /* Retrieve the system's memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); NonPagedSystemPoolEnd = ((ULONGLONG)MemoryLayout->NonPagedSystemPoolStart + MM::Manager::GetNumberOfSystemPtes() * MM_PAGE_SIZE); /* Map the page table hierarchy for the entire system PTE space */ MM::Pte::MapPPE(MemoryLayout->NonPagedSystemPoolStart, (PVOID)NonPagedSystemPoolEnd, &ValidPte); MM::Pte::MapPDE(MemoryLayout->NonPagedSystemPoolStart, (PVOID)NonPagedSystemPoolEnd, &ValidPte); /* Format the main block of system PTEs into a free list pool */ PointerPte = MM::Paging::GetPteAddress(MemoryLayout->NonPagedSystemPoolStart); InitializeSystemPtePool(PointerPte, MM::Manager::GetNumberOfSystemPtes(), SystemPteSpace); /* Reserve and zero a dedicated block of system PTEs */ FirstZeroingPte = ReserveSystemPtes(MM_RESERVED_ZERO_PTES + 1, SystemPteSpace); RTL::Memory::ZeroMemory(FirstZeroingPte, (MM_RESERVED_ZERO_PTES + 1) * MM::Paging::GetPteSize()); /* Use the first PTE of this block as a counter for available zeroing PTEs */ MM::Paging::SetPte(FirstZeroingPte, MM_RESERVED_ZERO_PTES, 0); } /** * Maps a range of virtual addresses at the PDE (Page Directory Entry) level. * * @param StartAddress * The beginning of the virtual address range to map. * * @param EndAddress * The end of the virtual address range to map. * * @param TemplatePde * A template PDE to use for creating new entries. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pte::MapPDE(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMPDE TemplatePde) { PMMPDE EndSpace, PointerPde; /* Get PDE addresses */ PointerPde = MM::Paging::GetPdeAddress(StartAddress); EndSpace = MM::Paging::GetPdeAddress(EndAddress); /* Iterate over all PDEs */ while(PointerPde <= EndSpace) { /* Check if PDE is already mapped */ if(!MM::Paging::PteValid(PointerPde)) { /* Map PDE */ MM::Paging::SetPte(TemplatePde, MM::Pfn::AllocateBootstrapPages(1), 0); MM::Paging::WritePte(PointerPde, *TemplatePde); /* Clear the page table */ RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPde), MM_PAGE_SIZE); } /* Get next table entry */ PointerPde = MM::Paging::GetNextPte(PointerPde); } } /** * Maps a range of virtual addresses at the PTE (Page Table Entry) level. * * @param StartAddress * The beginning of the virtual address range to map. * * @param EndAddress * The end of the virtual address range to map. * * @param TemplatePte * A template PTE to use for creating new entries. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pte::MapPTE(IN PVOID StartAddress, IN PVOID EndAddress, IN PMMPTE TemplatePte) { PMMPTE EndSpace, PointerPte; /* Get PTE addresses */ PointerPte = MM::Paging::GetPteAddress(StartAddress); EndSpace = MM::Paging::GetPteAddress(EndAddress); /* Iterate over all PTEs */ while(PointerPte <= EndSpace) { /* Check if PTE is already mapped */ if(!MM::Paging::PteValid(PointerPte)) { /* Map PTE */ MM::Paging::SetPte(TemplatePte, MM::Pfn::AllocateBootstrapPages(1), 0); MM::Paging::WritePte(PointerPte, *TemplatePte); /* Clear the page table */ RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPte), MM_PAGE_SIZE); } /* Get next table entry */ PointerPte = MM::Paging::GetNextPte(PointerPte); } } /** * Releases a block of system PTEs into a specified pool. * * @param StartingPte * A pointer to the first PTE to release. * * @param NumberOfPtes * The number of contiguous PTEs to release. * * @param SystemPtePoolType * Specifies the system PTE pool to release into. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID MM::Pte::ReleaseSystemPtes(IN PMMPTE StartingPte, IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType) { PMMPTE NextPte, PreviousPte, ReleasedPte; ULONG ClusterSize; /* Clear the PTEs before releasing them */ RtlZeroMemory(StartingPte, NumberOfPtes * MM::Paging::GetPteSize()); /* Raise runlevel and acquire lock to protect the PTE pool */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); /* Increment the total number of available PTEs in this pool */ TotalSystemFreePtes[SystemPtePoolType] += NumberOfPtes; /* Start at the head of the free list for this pool */ PreviousPte = &FirstSystemFreePte[SystemPtePoolType]; ReleasedPte = NULLPTR; /* Iterate through the free list to find adjacent blocks */ while(MM::Paging::GetNextEntry(PreviousPte) != MAXULONG) { /* Get the next free cluster to check its size */ NextPte = MM::Paging::AdvancePte(SystemPteBase, MM::Paging::GetNextEntry(PreviousPte)); ClusterSize = GetClusterSize(NextPte); /* Check if the released block is adjacent to the current free block */ if((MM::Paging::AdvancePte(NextPte, ClusterSize) == StartingPte) || (MM::Paging::AdvancePte(StartingPte, NumberOfPtes) == NextPte)) { /* Merge the blocks by adding their sizes */ NumberOfPtes += ClusterSize; /* Check if the current free block is before the released block */ if(NextPte < StartingPte) { /* The new merged block starts at the current free block's address */ StartingPte = NextPte; } /* Unlink the current free block as it is being merged */ MM::Paging::SetNextEntry(PreviousPte, MM::Paging::GetNextEntry(NextPte)); /* Check if the block represents more than one PTE */ if(!MM::Paging::GetOneEntry(NextPte)) { /* Clear block header and move to the size PTE */ MM::Paging::ClearPte(NextPte); NextPte = MM::Paging::GetNextPte(NextPte); } /* Clear the merged block */ MM::Paging::ClearPte(NextPte); /* Reset insertion point since block size/address changed due to merge */ ReleasedPte = NULLPTR; } else { /* Select the first free block large enough as insertion point */ if((ReleasedPte == NULLPTR) && (NumberOfPtes <= ClusterSize)) { /* Mark this as the insertion point */ ReleasedPte = PreviousPte; } /* Advance to the next free block */ PreviousPte = NextPte; } } /* Check if there is only one PTE to release */ if(NumberOfPtes == 1) { /* Mark it as a single-PTE block */ MM::Paging::SetOneEntry(StartingPte, 1); } else { /* Otherwise, mark it as a multi-PTE block */ MM::Paging::SetOneEntry(StartingPte, 0); /* The next PTE stores the size of the block */ NextPte = MM::Paging::GetNextPte(StartingPte); MM::Paging::SetNextEntry(NextPte, NumberOfPtes); } /* Check if no suitable insertion point was found */ if(ReleasedPte == NULLPTR) { /* Insert at the end of the list */ ReleasedPte = PreviousPte; } /* Link the new block into the free list */ MM::Paging::SetNextEntry(StartingPte, MM::Paging::GetNextEntry(ReleasedPte)); MM::Paging::SetNextEntry(ReleasedPte, MM::Paging::GetPteDistance(StartingPte, SystemPteBase)); } /** * Reserves a contiguous block of system PTEs from a specified pool. * * @param NumberOfPtes * The number of contiguous PTEs to reserve. * * @param SystemPtePoolType * Specifies the system PTE pool from which to allocate. * * @return This routine returns a pointer to the beginning of the reserved block, * or NULLPTR if not enough contiguous PTEs are available. * * @since XT 1.0 */ XTAPI PMMPTE MM::Pte::ReserveSystemPtes(IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType) { PMMPTE NextPte, PreviousPte, ReservedPte; ULONG ClusterSize; /* Raise runlevel and acquire lock to protect the PTE pool */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); /* Find a free PTE cluster large enough for the request */ if(!FindFreeCluster(NumberOfPtes, SystemPtePoolType, &NextPte, &PreviousPte)) { /* Out of system PTEs for this pool, return NULLPTR */ return NULLPTR; } /* We have the cluster, now get its size for the allocation logic below */ ClusterSize = GetClusterSize(NextPte); /* Unlink the found cluster from the free list for processing */ MM::Paging::SetNextEntry(PreviousPte, MM::Paging::GetNextEntry(NextPte)); /* Handle the allocation based on whether the cluster size is an exact match */ if(ClusterSize == NumberOfPtes) { /* Exact match, allocate the entire cluster */ ReservedPte = NextPte; /* Handle metadata cleanup for a single-PTE cluster */ if(MM::Paging::GetOneEntry(NextPte)) { /* Clear the PTE that held the list metadata */ MM::Paging::ClearPte(NextPte); NextPte = MM::Paging::GetNextPte(NextPte); } /* Clear the PTE that held the cluster size */ MM::Paging::ClearPte(NextPte); } else { /* Cluster is larger than needed, so it will be split */ ClusterSize -= NumberOfPtes; ReservedPte = MM::Paging::AdvancePte(NextPte, ClusterSize); /* Update metadata for the new, smaller leftover cluster */ if(ClusterSize == 1) { /* The leftover fragment is a single PTE */ MM::Paging::SetOneEntry(NextPte, 1); MM::Paging::ClearPte(ReservedPte); } else { /* The leftover fragment is larger than one PTE */ NextPte = MM::Paging::GetNextPte(NextPte); MM::Paging::SetNextEntry(NextPte, ClusterSize); } /* Find the correct sorted position to re-insert the leftover fragment */ PreviousPte = &FirstSystemFreePte[SystemPtePoolType]; while(MM::Paging::GetNextEntry(PreviousPte) != MAXULONG) { /* Get the next free cluster to check its size */ NextPte = MM::Paging::AdvancePte(SystemPteBase, MM::Paging::GetNextEntry(PreviousPte)); /* Check if the leftover fragment should be inserted here */ if(ClusterSize <= GetClusterSize(NextPte)) { /* Found the correct sorted position */ break; } /* Advance to the next entry */ PreviousPte = NextPte; } /* Get a pointer to the start of the leftover fragment */ NextPte = MM::Paging::AdvancePte(ReservedPte, -ClusterSize); /* Insert the leftover fragment back into the free list at its sorted position */ MM::Paging::SetNextEntry(NextPte, MM::Paging::GetNextEntry(PreviousPte)); MM::Paging::SetNextEntry(PreviousPte, MM::Paging::GetPteDistance(NextPte, SystemPteBase)); } /* Decrement the total number of available PTEs in this pool */ TotalSystemFreePtes[SystemPtePoolType] -= NumberOfPtes; /* Flush the TLB to ensure address translation consistency */ AR::CpuFunctions::FlushTlb(); /* Return a pointer to the start of the reserved PTE block */ return ReservedPte; } ================================================ FILE: xtoskrnl/po/idle.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/po/idle.cc * DESCRIPTION: Processor idle functionality support * DEVELOPERS: Rafal Kupiec */ #include /** * Initializes Processor Control Block's (PRCB) power state structures. * * @param Prcb * Supplies a pointer to the PRCB being initialized. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID PO::Idle::InitializeProcessorIdleState(IN OUT PKPROCESSOR_CONTROL_BLOCK Prcb) { /* Zero memory */ RTL::Memory::ZeroMemory(&Prcb->PowerState, sizeof(Prcb->PowerState)); /* Initialize default power state */ Prcb->PowerState.Idle0TimeLimit = 0xFFFFFFFF; Prcb->PowerState.CurrentThrottle = 100; Prcb->PowerState.CurrentThrottleIndex = 0; Prcb->PowerState.IdleFunction = Idle0Function; /* Initialize DPC and Timer */ KE::Dpc::InitializeDpc(&Prcb->PowerState.PerfDpc, PerfIdleDpc, Prcb); KE::Dpc::SetTargetProcessor(&Prcb->PowerState.PerfDpc, Prcb->CpuNumber); KE::Timer::InitializeTimer(&Prcb->PowerState.PerfTimer, SynchronizationTimer); } /** * Processor idle loop routine. * * @param PowerState * Supplies a pointer to the structere containing current processor power state. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID PO::Idle::Idle0Function(IN PPROCESSOR_POWER_STATE PowerState) { UNIMPLEMENTED; } /** * Switches CPU between different performance levels. * * @param PowerState * Supplies a pointer to the structure containing IDLE processor power state. * * @return This routine does not return any value. * * @since NT 5.1 */ XTAPI VOID PO::Idle::PerfIdle(PPROCESSOR_POWER_STATE PowerState) { UNIMPLEMENTED; } /** * Checks if CPU is running at the maximum (performance) frequency. * * @param Dpc * Supplies a pointer to the DPC object. * * @param DeferredContext * Supplies a pointer to memory area containing current CPU's PRCB. * * @param SystemArgument1 * Supplies a pointer to an unused system argument. * * @param SystemArgument2 * Supplies a pointer to an unused system argument. * * @return This routine does not return any value. * * @since NT 5.1 */ XTAPI VOID PO::Idle::PerfIdleDpc(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2) { UNIMPLEMENTED; } ================================================ FILE: xtoskrnl/rtl/amd64/dispatch.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/amd64/dispatch.cc * DESCRIPTION: Dispatching support for AMD64 architecture * DEVELOPERS: Rafal Kupiec */ #include /** * Returns the stack limits for the current thread. * * @param StackBase * Supplies a pointer to memory area, where the stack base will be stored. * * @param StackLimit * Suppliws a pointer to memory area, where the stack limit will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID RTL::Dispatcher::GetStackLimits(OUT PULONG_PTR StackBase, OUT PULONG_PTR StackLimit) { PKTHREAD Thread = KE::Processor::GetCurrentThread(); *StackBase = (ULONG_PTR)Thread->StackBase; *StackLimit = (ULONG_PTR)Thread->StackLimit; } ================================================ FILE: xtoskrnl/rtl/amd64/exsup.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/amd64/exsup.cc * DESCRIPTION: Exception handling for AMD64 architecture * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Handles SEH structured exception frames. * * @param ExceptionRecord * A pointer to the exception record. * * @param EstablisherFrame * The address of the base of the fixed stack allocation. * * @param ContextRecord * A pointer to the context record at the time the exception was raised. * * @param DispatcherContext * A pointer to the dispatcher context for the function. * * @return This routine returns an exception disposition value if the exception was not handled by any filter. * * @since XT 1.0 */ XTCLINK XTAPI EXCEPTION_DISPOSITION __C_specific_handler(IN PEXCEPTION_RECORD ExceptionRecord, IN PVOID EstablisherFrame, IN OUT PCONTEXT ContextRecord, IN OUT PVOID DispatcherContext) { UNIMPLEMENTED; /* Continue execution */ return ExceptionContinueExecution; } /** * Handles C++ structured exception frames. This implementation displays a panic screen and halts the system. * * @param ExceptionRecord * A pointer to the exception record that is passed to the possible catch statements. * * @param EstablisherFrame * A pointer to the stack frame that is used to handle the exception. * * @param ContextRecord * A pointer to the context record (not used on Intel CPUs). * * @param DispatcherContext * A pointer to the dispatcher provding information about function entry and stack frame (not used on Intel CPUs). * * @return This routine returns an exception disposition value if the exception was not handled by any filter. * * @since XT 1.0 */ XTCLINK XTCDECL EXCEPTION_DISPOSITION __CxxFrameHandler3(IN PEXCEPTION_RECORD ExceptionRecord, IN PVOID EstablisherFrame, IN OUT PCONTEXT ContextRecord, IN OUT PVOID DispatcherContext) { UNIMPLEMENTED; /* Disable interrupts and hang */ AR::CpuFunctions::ClearInterruptFlag(); KE::Crash::Panic(0); /* Continue search */ return ExceptionContinueSearch; } /** * Finds the appropriate exception handler to process the current exception. * * @param ExceptionRecord * A pointer to the exception record providing information about the specific exception. * * @param Registration * A pointer to the record that indicates which scope table should be used to find the exception handler. * * @param Context * Reserved. * * @param Dispatcher * Reserved. * * @return This routine returns DISPOSITION_DISMISS or DISPOSITION_CONTINUE_SEARCH. * * @since XT 1.0 */ XTCLINK XTCDECL INT _except_handler3(IN PEXCEPTION_RECORD ExceptionRecord, IN PVOID Registration, IN PCONTEXT Context, IN PVOID Dispatcher) { UNIMPLEMENTED; /* Handler not found */ return 0; } /** * Handles pure virtual function call error. This implementation displays a panic screen and halts the system. * * @return This function does not return any value. * * @since XT 1.0 */ XTCLINK XTCDECL VOID _purecall(VOID) { UNIMPLEMENTED; /* Disable interrupts and hang */ AR::CpuFunctions::ClearInterruptFlag(); KE::Crash::Panic(0); } ================================================ FILE: xtoskrnl/rtl/amd64/intrin.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/amd64/intrin.cc * DESCRIPTION: Compiler intrinsic support routines * DEVELOPERS: Aiken Harris */ #include ================================================ FILE: xtoskrnl/rtl/atomic.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/atomic.cc * DESCRIPTION: Atomic operations support * DEVELOPERS: Rafal Kupiec */ #include /** * Performs an atomic bitwise AND operation on the 8-bit value. * * @param Address * Supplies the address of the value on which the bitwise AND operation is to be performed. * * @param Mask * Supplies the mask with which the bitwise AND operation is to be performed * * @return This routine returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL CHAR RTL::Atomic::And8(IN PCHAR Address, IN CHAR Mask) { return __sync_fetch_and_and(Address, Mask); } /** * Performs an atomic bitwise AND operation on the 16-bit value. * * @param Address * Supplies the address of the value on which the bitwise AND operation is to be performed. * * @param Mask * Supplies the mask with which the bitwise AND operation is to be performed * * @return This routine returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL SHORT RTL::Atomic::And16(IN PSHORT Address, IN SHORT Mask) { return __sync_fetch_and_and(Address, Mask); } /** * Performs an atomic bitwise AND operation on the 32-bit value. * * @param Address * Supplies the address of the value on which the bitwise AND operation is to be performed. * * @param Mask * Supplies the mask with which the bitwise AND operation is to be performed * * @return This routine returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL LONG RTL::Atomic::And32(IN PLONG Address, IN LONG Mask) { return __sync_fetch_and_and(Address, Mask); } /** * Performs an atomic bitwise AND operation on the 32-bit or 64-bit value depending or architecture. * * @param Address * Supplies the address of the value on which the bitwise AND operation is to be performed. * * @param Mask * Supplies the mask with which the bitwise AND operation is to be performed * * @return This routine returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL LONG_PTR RTL::Atomic::And64(IN PLONG_PTR Address, IN LONG_PTR Mask) { return __sync_fetch_and_and(Address, Mask); } /** * Performs an atomic test of the specified bit of the specified long value and sets it to 1. * * @param Base * Specifies a pointer to the variable. * * @param Offset * Specifies the bit position to be tested. * * @return Returns a value of the specified bit. * * @since XT 1.0 */ XTFASTCALL UCHAR RTL::Atomic::BitTestAndSet(IN PLONG Base, IN LONG Offset) { return (__atomic_fetch_or(Base, 1l << Offset, __ATOMIC_SEQ_CST) >> Offset) & 1; } /** * Performs an atomic test of the specified bit of the specified 64-bit long value and sets it to 1. * * @param Base * Specifies a pointer to the variable. * * @param Offset * Specifies the bit position to be tested. * * @return Returns a value of the specified bit. * * @since XT 1.0 */ XTFASTCALL UCHAR RTL::Atomic::BitTestAndSet64(IN PLONGLONG Base, IN LONGLONG Offset) { return (__atomic_fetch_or(Base, 1ll << Offset, __ATOMIC_SEQ_CST) >> Offset) & 1; } /** * Performs atomically compare exchange operation on the 8-bit value. * * @param Address * Supplies the address of the value to compare and potentially exchange. * * @param Comperand * Supplies the value to compare against. * * @param Exchange * Supplies the value to write if the comparison returns equality. * * @return This routine returns the original value at the given address. * * @since XT 1.0 */ XTFASTCALL CHAR RTL::Atomic::CompareExchange8(IN PCHAR Address, IN CHAR Comperand, IN CHAR Exchange) { return __sync_val_compare_and_swap(Address, Comperand, Exchange); } /** * Performs atomically compare exchange operation on the 16-bit value. * * @param Address * Supplies the address of the value to compare and potentially exchange. * * @param Comperand * Supplies the value to compare against. * * @param Exchange * Supplies the value to write if the comparison returns equality. * * @return This routine returns the original value at the given address. * * @since XT 1.0 */ XTFASTCALL SHORT RTL::Atomic::CompareExchange16(IN PSHORT Address, IN SHORT Comperand, IN SHORT Exchange) { return __sync_val_compare_and_swap(Address, Comperand, Exchange); } /** * Performs atomically compare exchange operation on the 32-bit value. * * @param Address * Supplies the address of the value to compare and potentially exchange. * * @param Comperand * Supplies the value to compare against. * * @param Exchange * Supplies the value to write if the comparison returns equality. * * @return This routine returns the original value at the given address. * * @since XT 1.0 */ XTFASTCALL LONG RTL::Atomic::CompareExchange32(IN PLONG Address, IN LONG Comperand, IN LONG Exchange) { return __sync_val_compare_and_swap(Address, Comperand, Exchange); } /** * Performs atomically compare exchange operation on the 32-bit or 64-bit value depending or architecture. * * @param Address * Supplies the address of the value to compare and potentially exchange. * * @param Comperand * Supplies the value to compare against. * * @param Exchange * Supplies the value to write if the comparison returns equality. * * @return This routine returns the original value at the given address. * * @since XT 1.0 */ XTFASTCALL LONG_PTR RTL::Atomic::CompareExchange64(IN PLONG_PTR Address, IN LONG_PTR Comperand, IN LONG_PTR Exchange) { return __sync_val_compare_and_swap(Address, Comperand, Exchange); } /** * Performs atomically compare exchange operation. * * @param Address * Supplies the address of the value to compare and potentially exchange. * * @param Comperand * Supplies a pointer to the value to compare against. * * @param Exchange * Supplies a pointer to the value to write if the comparison returns equality. * * @return This routine returns the original value at the given address. * * @since XT 1.0 */ XTFASTCALL PVOID RTL::Atomic::CompareExchangePointer(IN PVOID *Address, IN PVOID Comperand, IN PVOID Exchange) { return (PVOID)__sync_val_compare_and_swap(Address, Comperand, Exchange); } /** * Performs atomically decrement of the 8-bit value. * * @param Address * Supplies the address of the value to decrement. * * @return This routine returns the decremented value. * * @since XT 1.0 */ XTFASTCALL CHAR RTL::Atomic::Decrement8(IN PCHAR Address) { return __sync_sub_and_fetch(Address, 1); } /** * Performs atomically decrement of the 16-bit value. * * @param Address * Supplies the address of the value to decrement. * * @return This routine returns the decremented value. * * @since XT 1.0 */ XTFASTCALL SHORT RTL::Atomic::Decrement16(IN PSHORT Address) { return __sync_sub_and_fetch(Address, 1); } /** * Performs atomically decrement of the 32-bit value. * * @param Address * Supplies the address of the value to decrement. * * @return This routine returns the decremented value. * * @since XT 1.0 */ XTFASTCALL LONG RTL::Atomic::Decrement32(IN PLONG Address) { return __sync_sub_and_fetch(Address, 1); } /** * Performs atomically decrement of the 32-bit or 64-bit value depending or architecture. * * @param Address * Supplies the address of the value to decrement. * * @return This routine returns the decremented value. * * @since XT 1.0 */ XTFASTCALL LONG_PTR RTL::Atomic::Decrement64(IN PLONG_PTR Address) { return __sync_sub_and_fetch(Address, 1); } /** * Performs atomically operation on the 8-bit value. * * @param Address * Supplies the address of the value to exchange with. * * @param Exchange * Supplies the value to write to the address. * * @return This routine returns the original value at the given address. * * @since XT 1.0 */ XTFASTCALL CHAR RTL::Atomic::Exchange8(IN PCHAR Address, IN CHAR Exchange) { return __sync_lock_test_and_set(Address, Exchange); } /** * Performs atomically operation on the 16-bit value. * * @param Address * Supplies the address of the value to exchange with. * * @param Exchange * Supplies the value to write to the address. * * @return This routine returns the original value at the given address. * * @since XT 1.0 */ XTFASTCALL SHORT RTL::Atomic::Exchange16(IN PSHORT Address, IN SHORT Exchange) { return __sync_lock_test_and_set(Address, Exchange); } /** * Performs atomically operation on the 32-bit value. * * @param Address * Supplies the address of the value to exchange with. * * @param Exchange * Supplies the value to write to the address. * * @return This routine returns the original value at the given address. * * @since XT 1.0 */ XTFASTCALL LONG RTL::Atomic::Exchange32(IN PLONG Address, IN LONG Exchange) { return __sync_lock_test_and_set(Address, Exchange); } /** * Performs atomically operation on the 32-bit or 64-bit value depending or architecture. * * @param Address * Supplies the address of the value to exchange with. * * @param Exchange * Supplies the value to write to the address. * * @return This routine returns the original value at the given address. * * @since XT 1.0 */ XTFASTCALL LONG_PTR RTL::Atomic::Exchange64(IN PLONG_PTR Address, IN LONG_PTR Exchange) { return __sync_lock_test_and_set(Address, Exchange); } /** * Performs atomically addition of the 8-bit value. * * @param Address * Supplies the address of the original value. * * @param Value * Supplies a value, to be add to variable found at specified address. * * @return Returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL CHAR RTL::Atomic::ExchangeAdd8(IN PCHAR Address, IN CHAR Value) { return __sync_fetch_and_add(Address, Value); } /** * Performs atomically addition of the 16-bit value. * * @param Address * Supplies the address of the original value. * * @param Value * Supplies a value, to be add to variable found at specified address. * * @return Returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL SHORT RTL::Atomic::ExchangeAdd16(IN PSHORT Address, IN SHORT Value) { return __sync_fetch_and_add(Address, Value); } /** * Performs atomically addition of the 32-bit value. * * @param Address * Supplies the address of the original value. * * @param Value * Supplies a value, to be add to variable found at specified address. * * @return Returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL LONG RTL::Atomic::ExchangeAdd32(IN PLONG Address, IN LONG Value) { return __sync_fetch_and_add(Address, Value); } /** * Performs atomically addition of the 32-bit or 64-bit value depending or architecture. * * @param Address * Supplies the address of the original value. * * @param Value * Supplies a value, to be add to variable found at specified address. * * @return Returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL LONG_PTR RTL::Atomic::ExchangeAdd64(IN PLONG_PTR Address, IN LONG_PTR Value) { return __sync_fetch_and_add(Address, Value); } /** * Performs atomically exchange operation. * * @param Address * Supplies the address of the value to exchange with. * * @param Exchange * Supplies a pointer to the value to write to the address. * * @return This routine returns the original value at the given address. * * @since XT 1.0 */ XTFASTCALL PVOID RTL::Atomic::ExchangePointer(IN PVOID *Address, IN PVOID Exchange) { __sync_synchronize(); return (PVOID)__sync_lock_test_and_set(Address, Exchange); } /** * Removes all entries from single linked list. * * @param Header * Supplies a pointer to the header of linked list. * * @return This routine returns a pointer to the original list, or NULLPTR if the list was already empty. * * @since XT 1.0 */ XTFASTCALL PSINGLE_LIST_ENTRY RTL::Atomic::FlushSingleList(IN PSINGLE_LIST_HEADER Header) { return (PSINGLE_LIST_ENTRY)Exchange64((PLONG_PTR)&Header->Alignment, (LONGLONG)NULLPTR); } /** * Performs atomically increment of the 8-bit value. * * @param Address * Supplies the address of the value to increment. * * @return This routine returns the incremented value. * * @since XT 1.0 */ XTFASTCALL CHAR RTL::Atomic::Increment8(IN PCHAR Address) { return __sync_add_and_fetch(Address, 1); } /** * Performs atomically increment of the 16-bit value. * * @param Address * Supplies the address of the value to increment. * * @return This routine returns the incremented value. * * @since XT 1.0 */ XTFASTCALL SHORT RTL::Atomic::Increment16(IN PSHORT Address) { return __sync_add_and_fetch(Address, 1); } /** * Performs atomically increment of the 32-bit value. * * @param Address * Supplies the address of the value to increment. * * @return This routine returns the incremented value. * * @since XT 1.0 */ XTFASTCALL LONG RTL::Atomic::Increment32(IN PLONG Address) { return __sync_add_and_fetch(Address, 1); } /** * Performs atomically increment of the 32-bit or 64-bit value depending or architecture. * * @param Address * Supplies the address of the value to increment. * * @return This routine returns the incremented value. * * @since XT 1.0 */ XTFASTCALL LONG_PTR RTL::Atomic::Increment64(IN PLONG_PTR Address) { return __sync_add_and_fetch(Address, 1); } /** * Performs an atomic bitwise OR operation on the 8-bit value. * * @param Address * Supplies the address of the value on which the bitwise OR operation is to be performed. * * @param Mask * Supplies the mask with which the bitwise OR operation is to be performed * * @return This routine returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL CHAR RTL::Atomic::Or8(IN PCHAR Address, IN CHAR Mask) { return __sync_fetch_and_or(Address, Mask); } /** * Performs an atomic bitwise OR operation on the 16-bit value. * * @param Address * Supplies the address of the value on which the bitwise OR operation is to be performed. * * @param Mask * Supplies the mask with which the bitwise OR operation is to be performed * * @return This routine returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL SHORT RTL::Atomic::Or16(IN PSHORT Address, IN SHORT Mask) { return __sync_fetch_and_or(Address, Mask); } /** * Performs an atomic bitwise OR operation on the 32-bit value. * * @param Address * Supplies the address of the value on which the bitwise OR operation is to be performed. * * @param Mask * Supplies the mask with which the bitwise OR operation is to be performed * * @return This routine returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL LONG RTL::Atomic::Or32(IN PLONG Address, IN LONG Mask) { return __sync_fetch_and_or(Address, Mask); } /** * Performs an atomic bitwise OR operation on the 32-bit or 64-bit value depending or architecture. * * @param Address * Supplies the address of the value on which the bitwise OR operation is to be performed. * * @param Mask * Supplies the mask with which the bitwise OR operation is to be performed * * @return This routine returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL LONG_PTR RTL::Atomic::Or64(IN PLONG_PTR Address, IN LONG_PTR Mask) { return __sync_fetch_and_or(Address, Mask); } /** * Removes and returns the first entry from single linked list. * * @param Header * Supplies a pointer to the header of a single linked list. * * @return This routine returns a pointer to the removed element, or NULLPTR if the list was empty. * * @since XT 1.0 */ XTFASTCALL PSINGLE_LIST_ENTRY RTL::Atomic::PopEntrySingleList(IN PSINGLE_LIST_HEADER Header) { PSINGLE_LIST_ENTRY ListHead, FirstEntry, NextEntry; /* Save header and first entry */ ListHead = (PSINGLE_LIST_ENTRY)Header; FirstEntry = ListHead->Next; do { /* Check if list is not empty */ if(!FirstEntry) { /* Empty list */ return NULLPTR; } /* Update link */ NextEntry = FirstEntry; /* Compare and exchange */ FirstEntry = (PSINGLE_LIST_ENTRY)CompareExchange64((PLONG_PTR)ListHead, (LONG_PTR)FirstEntry->Next, (LONG_PTR)FirstEntry); } while(FirstEntry != NextEntry); /* Return removed element */ return FirstEntry; } /** * Inserts new entry at the beginning of single linked list. * * @param Header * Supplies a pointer to the header of linked list. * * @param Entry * Supplies a pointer to entry, that will be inserted into linked list. * * @return This routine returns a pointer to original heading, or NULLPTR if the list was originally empty. * * @since XT 1.0 */ XTFASTCALL PSINGLE_LIST_ENTRY RTL::Atomic::PushEntrySingleList(IN PSINGLE_LIST_HEADER Header, IN PSINGLE_LIST_ENTRY Entry) { PSINGLE_LIST_ENTRY ListHead, ListEntry, FirstEntry, NextEntry; /* Save header and new entry */ ListHead = (PSINGLE_LIST_ENTRY)Header; ListEntry = Entry; /* Save next link in new first element */ FirstEntry = ListHead->Next; do { /* Update links */ ListEntry->Next = FirstEntry; NextEntry = FirstEntry; /* Compare and exchange */ FirstEntry = (PSINGLE_LIST_ENTRY)CompareExchange64((PLONG_PTR)ListHead, (LONG_PTR)ListEntry, (LONG_PTR)FirstEntry); } while(FirstEntry != NextEntry); /* Return original first element */ return FirstEntry; } /** * Performs an atomic bitwise XOR operation on the 8-bit value. * * @param Address * Supplies the address of the value on which the bitwise XOR operation is to be performed. * * @param Mask * Supplies the mask with which the bitwise XOR operation is to be performed * * @return This routine returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL CHAR RTL::Atomic::Xor8(IN PCHAR Address, IN CHAR Mask) { return __sync_fetch_and_xor(Address, Mask); } /** * Performs an atomic bitwise XOR operation on the 16-bit value. * * @param Address * Supplies the address of the value on which the bitwise XOR operation is to be performed. * * @param Mask * Supplies the mask with which the bitwise XOR operation is to be performed * * @return This routine returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL SHORT RTL::Atomic::Xor16(IN PSHORT Address, IN SHORT Mask) { return __sync_fetch_and_xor(Address, Mask); } /** * Performs an atomic bitwise XOR operation on the 32-bit value. * * @param Address * Supplies the address of the value on which the bitwise XOR operation is to be performed. * * @param Mask * Supplies the mask with which the bitwise XOR operation is to be performed * * @return This routine returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL LONG RTL::Atomic::Xor32(IN PLONG Address, IN LONG Mask) { return __sync_fetch_and_xor(Address, Mask); } /** * Performs an atomic bitwise XOR operation on the 32-bit or 64-bit value depending or architecture. * * @param Address * Supplies the address of the value on which the bitwise XOR operation is to be performed. * * @param Mask * Supplies the mask with which the bitwise XOR operation is to be performed * * @return This routine returns the initial value at the given address. * * @since XT 1.0 */ XTFASTCALL LONG_PTR RTL::Atomic::Xor64(IN PLONG_PTR Address, IN LONG_PTR Mask) { return __sync_fetch_and_xor(Address, Mask); } ================================================ FILE: xtoskrnl/rtl/bitmap.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/bitmap.cc * DESCRIPTION: Bit maps support related routines * DEVELOPERS: Rafal Kupiec */ #include /** * Clears all bits in the bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID RTL::BitMap::ClearAllBits(IN PRTL_BITMAP BitMap) { /* Clear all bits */ RTL::Memory::SetMemory(BitMap->Buffer, 0, ((BitMap->Size + BITS_PER_LONG - 1) / BITS_PER_LONG) * sizeof(ULONG_PTR)); } /** * Clears a single bit in the bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @param Bit * Specifies the number of the bit to be cleared. * * @return This routine does not return any value. * * @since NT 5.1 */ XTAPI VOID RTL::BitMap::ClearBit(IN PRTL_BITMAP BitMap, IN ULONG_PTR Bit) { /* Check if bit is in range */ if(Bit >= BitMap->Size) { /* Supplied bit exceeds bit map size */ return; } /* Clear specified bit */ BitMap->Buffer[Bit / BITS_PER_LONG] &= ~(1 << (Bit & (BITS_PER_LONG - 1))); } /** * Clears a specified set of bits within a bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @param StartingIndex * Supplies the starting index of the first bit to clear. * * @param Length * Supplies the length (number of bits) to clear. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID RTL::BitMap::ClearBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR StartingIndex, IN ULONG_PTR Length) { ULONG_PTR BitOffset, Mask; PULONG_PTR Buffer; /* Make sure there is anything to clear */ if(!Length) { /* No bits to clear */ return; } /* Get pointer to first byte to clear and calculate bit offset */ Buffer = &BitMap->Buffer[StartingIndex / BITS_PER_LONG]; BitOffset = StartingIndex & (BITS_PER_LONG - 1); /* Check if bit offset is not zero */ if(BitOffset) { /* Get mask and calculate new bit offset */ Mask = MAXULONG_PTR << BitOffset; BitOffset = BITS_PER_LONG - BitOffset; /* Check if there are enough bits to clear */ if(Length < BitOffset) { /* Recalculate bit offset and fixup the mask */ BitOffset -= Length; Mask = Mask << BitOffset >> BitOffset; /* Clear bits and return */ *Buffer &= ~Mask; return; } /* Clear bits, recalculate length and advance buffer pointer */ *Buffer &= ~Mask; Length -= BitOffset; Buffer++; } /* Clear remaining bits */ RTL::Memory::SetMemory(Buffer, 0, Length >> 3); /* Look for any remaining bits to clear */ Buffer += Length / BITS_PER_LONG; Length &= BITS_PER_LONG - 1; if(Length) { /* Clear what's left */ *Buffer &= MAXULONG_PTR << Length; } } /** * Searches the bit map for a contiguous region of set bits and clears them. * * @param BitMap * Supplies a pointer to the bit map. * * @param Length * Supplies the length of contiguous region (number of set bits) to look for. * * @param Index * Supplies the index of the first bit to start the search at a given position. * * @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found. * * @since XT 1.0 */ XTAPI ULONG RTL::BitMap::ClearSetBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index) { ULONG_PTR StartingIndex; /* Find set bits */ StartingIndex = FindSetBits(BitMap, Length, Index); /* Check if set bits were found */ if(StartingIndex != MAXULONG_PTR) { /* Clear bits */ ClearBits(BitMap, StartingIndex, Length); } /* Return position of bits found */ return StartingIndex; } /** * Counts the number of either set or clear bits in the contiguous region of the bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @param Length * Supplies the maximum length (number of bits) to count. * * @param StartingIndex * Supplies the starting index of the first bit to count. * * @param SetBits * Specifies whether count bits that are set or clear. * * @return This routine returns the number of equal bits found in the contiguous region. * * @since XT 1.0 */ XTAPI ULONG_PTR RTL::BitMap::CountBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR StartingIndex, IN BOOLEAN SetBits) { PULONG_PTR Buffer, BufferEnd; ULONG_PTR BitOffset, Size; ULONGLONG Value; /* Get pointers to first and last bytes to check */ Buffer = &BitMap->Buffer[StartingIndex / BITS_PER_LONG]; BufferEnd = Buffer + ((Length + BITS_PER_LONG - 1) / BITS_PER_LONG); /* Get offset and value */ BitOffset = StartingIndex & (BITS_PER_LONG - 1); Value = (SetBits ? ~*Buffer : *Buffer) >> BitOffset << BitOffset; /* Find first bit set until the end of the buffer */ while(!Value && Buffer + 1 < BufferEnd) { /* Advance buffer pointer and get value */ Value = SetBits ? ~*(++Buffer) : *(++Buffer); } /* Check if value found */ if(!Value) { /* No bits found, return length */ return Length; } /* Calculate size */ Size = ((Buffer - BitMap->Buffer) * BITS_PER_LONG) - StartingIndex + (ULONG_PTR)RTL::Math::CountTrailingZeroes64(Value); /* Return whatever is smaller */ return Size > Length ? Length : Size; } /** * Dumps the contents of the bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID RTL::BitMap::DumpBitMap(IN PRTL_BITMAP BitMap) { ULONG_PTR Index; /* Dump bit map buffer information */ DebugPrint(L"BitMap Buffer: 0x%zX (%lu bytes)\n", BitMap->Buffer, BitMap->Size); /* Dump bit map buffer content */ for(Index = 0; Index < (BitMap->Size + BITS_PER_LONG - 1) / BITS_PER_LONG; Index++) { DebugPrint(L" %8zu: %08lx\n", Index, BitMap->Buffer[Index]); } } /** * Searches the bit map for a contiguous region of either set or clear bits. * * @param BitMap * Supplies a pointer to the bit map. * * @param Length * Supplies the length (number of equal bits) to look for. * * @param StartingIndex * Supplies the starting index of the first bit to start the search at a given position. * * @param SetBits * Specifies whether count bits that are set or clear. * * @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found. * * @since XT 1.0 */ XTAPI ULONG_PTR RTL::BitMap::FindBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR StartingIndex, IN BOOLEAN SetBits) { ULONG_PTR BitMapEnd, BitOffset, Size; ULONG Tries; /* Validate length */ if(Length > BitMap->Size) { /* Length exceeds bit map size, return MAXULONG_PTR */ return (ULONG_PTR)-1; } else if(!Length) { /* Length not specified, return starting index */ return StartingIndex; } /* Check if starting index is in range of bit map size */ if(StartingIndex >= BitMap->Size) { /* Starting index exceeds bit map size, start from the beginning */ StartingIndex = 0; } /* Try from starting index */ BitOffset = StartingIndex; BitMapEnd = BitMap->Size; /* At least two tries are required */ Tries = (StartingIndex != 0) + 2; while(Tries) { /* Find until the end of the bit map */ while(BitOffset + Length < BitMapEnd) { /* Increment offset */ BitOffset += CountBits(BitMap, BitMap->Size - BitOffset, BitOffset, !SetBits); if(BitOffset + Length > BitMapEnd) { /* No match found, break loop execution */ break; } /* Count bits in the contiguous region and check if match found */ Size = CountBits(BitMap, Length, BitOffset, SetBits); if(Size >= Length) { /* Match found, return offset */ return BitOffset; } /* Increment offset */ BitOffset += Size; } /* Try again if possible */ Tries--; if(Tries) { /* Restart from the beginning up to the starting index */ BitOffset = 0; BitMapEnd = StartingIndex; } } /* No match found, return MAXULONG_PTR */ return (ULONG_PTR)-1; } /** * Searches the bit map for a contiguous region of clear bits. * * @param BitMap * Supplies a pointer to the bit map. * * @param Length * Supplies the length of contiguous region (number of clear bits) to look for. * * @param Index * Supplies the index of the first bit to start the search at a given position. * * @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found. * * @since NT 3.5 */ XTAPI ULONG_PTR RTL::BitMap::FindClearBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index) { /* Find clear bits */ return FindBits(BitMap, Length, Index, FALSE); } /** * Searches the bit map for a contiguous region of set bits. * * @param BitMap * Supplies a pointer to the bit map. * * @param Length * Supplies the length of contiguous region (number of set bits) to look for. * * @param Index * Supplies the index of the first bit to start the search at a given position. * * @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found. * * @since NT 3.5 */ XTAPI ULONG_PTR RTL::BitMap::FindSetBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index) { /* Find set bits */ return FindBits(BitMap, Length, Index, TRUE); } /** * Initializes a bit map. * * @param BitMap * Supplies a pointer to the bit map to initialize. * * @param Buffer * Supplies a pointer to the buffer that will be used as a bit map. * * @param Size * Supplies a size of the bit map. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID RTL::BitMap::InitializeBitMap(IN PRTL_BITMAP BitMap, IN PULONG_PTR Buffer, IN ULONG Size) { /* Initialize bit map */ BitMap->Buffer = Buffer; BitMap->Size = Size; } /** * Sets all bits in the bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID RTL::BitMap::SetAllBits(IN PRTL_BITMAP BitMap) { /* Set all bits */ RTL::Memory::SetMemory(BitMap->Buffer, 0xFF, ((BitMap->Size + BITS_PER_LONG - 1) / BITS_PER_LONG) * sizeof(ULONG_PTR)); } /** * Sets a single bit in the bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @param Bit * Specifies the number of the bit to be set. * * @return This routine does not return any value. * * @since NT 5.1 */ XTAPI VOID RTL::BitMap::SetBit(IN PRTL_BITMAP BitMap, IN ULONG_PTR Bit) { /* Check if bit is in range */ if(Bit >= BitMap->Size) { /* Supplied bit exceeds bit map size */ return; } /* Set specified bit */ BitMap->Buffer[Bit / BITS_PER_LONG] |= 1 << (Bit & (BITS_PER_LONG - 1)); } /** * Sets a specified set of bits within a bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @param StartingIndex * Supplies the starting index of the first bit to set. * * @param Length * Supplies the length (number of bits) to set. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID RTL::BitMap::SetBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR StartingIndex, IN ULONG_PTR Length) { ULONG_PTR BitOffset, Mask; PULONG_PTR Buffer; /* Make sure there is anything to set */ if(!Length) { /* No bits to set */ return; } /* Get pointer to first byte to clear and calculate bit offset */ Buffer = &BitMap->Buffer[StartingIndex / BITS_PER_LONG]; BitOffset = StartingIndex & (BITS_PER_LONG - 1); /* Check if bit offset is not zero */ if(BitOffset) { /* Get mask and calculate new bit offset */ Mask = MAXULONG_PTR << BitOffset; BitOffset = BITS_PER_LONG - BitOffset; /* Check if there are enough bits to set */ if(Length < BitOffset) { /* Recalculate bit offset and fixup the mask */ BitOffset -= Length; Mask = Mask << BitOffset >> BitOffset; /* Set bits and return */ *Buffer |= Mask; return; } /* Set bits, recalculate length and advance buffer pointer */ *Buffer |= Mask; Buffer++; Length -= BitOffset; } /* Set remaining bits */ RTL::Memory::SetMemory(Buffer, 0xFF, Length >> 3); /* Look for any remaining bits to set */ Buffer += Length / BITS_PER_LONG; Length &= BITS_PER_LONG - 1; if(Length) { /* Set what's left */ *Buffer |= ~(MAXULONG_PTR << Length); } } /** * Searches the bit map for a contiguous region of clear bits and sets them. * * @param BitMap * Supplies a pointer to the bit map. * * @param Length * Supplies the length of contiguous region (number of clear bits) to look for. * * @param Index * Supplies the index of the first bit to start the search at a given position. * * @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found. * * @since XT 1.0 */ XTAPI ULONG RTL::BitMap::SetClearBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index) { ULONG_PTR StartingIndex; /* Find clear bits */ StartingIndex = FindClearBits(BitMap, Length, Index); /* Check if clear bits were found */ if(StartingIndex != MAXULONG_PTR) { /* Set bits */ SetBits(BitMap, StartingIndex, Length); } /* Return position of bits found */ return StartingIndex; } /** * Tests a state of a single bit in the bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @param Bit * Specifies the number of the bit to be tested. * * @return This routine returns TRUE when bit is set, or FALSE otherwise. * * @since NT 5.1 */ XTAPI BOOLEAN RTL::BitMap::TestBit(IN PRTL_BITMAP BitMap, IN ULONG_PTR Bit) { /* Check if bit is in range */ if(Bit >= BitMap->Size) { /* Supplied bit exceeds bit map size, return FALSE */ return FALSE; } /* Test specified bit and return result */ return ((BitMap->Buffer[Bit / BITS_PER_LONG] >> (Bit & (BITS_PER_LONG - 1))) & 1) ? TRUE : FALSE; } ================================================ FILE: xtoskrnl/rtl/data.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/data.cc * DESCRIPTION: Runtime Library global and static data * DEVELOPERS: Rafal Kupiec */ #include /* This is required for floating numbers to keep LLVM happy */ XTCLINK INT _fltused = 0xFEEDBULL; /* Lookup table for days in a month, Index 0 is normal year, Index 1 is leap year */ CUSHORT RTL::Time::DaysInMonth[2][12] = { {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} }; ================================================ FILE: xtoskrnl/rtl/endian.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/endian.cc * DESCRIPTION: Endian conversion routines * DEVELOPERS: Rafal Kupiec */ #include /** * This routine converts endianness on 16bit value. * * @param Source * Supplies a value to swap bytes. * * @return Swapped 16bit value. * * @since XT 1.0 */ XTFASTCALL USHORT RTL::Endianness::SwapByte16(IN USHORT Source) { return (USHORT)(((Source >> 8) & 0x00FF) | ((Source << 8) & 0xFF00)); } /** * This routine converts endianness on 32bit value. * * @param Source * Supplies a value to swap bytes. * * @return Swapped 32bit value. * * @since XT 1.0 */ XTFASTCALL ULONG RTL::Endianness::SwapByte32(IN ULONG Source) { return (ULONG)(((Source >> 24) & 0x000000FF) | ((Source >> 8) & 0x0000FF00) | ((Source << 8) & 0x00FF0000) | ((Source << 24) & 0xFF000000)); } /** * This routine converts endianness on 64bit value. * * @param Source * Supplies a value to swap bytes. * * @return Swapped 64bit value. * * @since XT 1.0 */ XTFASTCALL ULONGLONG RTL::Endianness::SwapByte64(IN ULONGLONG Source) { return (ULONGLONG)(((Source >> 56) & 0x00000000000000FF) | ((Source >> 40) & 0x000000000000FF00) | ((Source >> 24) & 0x0000000000FF0000) | ((Source >> 8) & 0x00000000FF000000) | ((Source << 8) & 0x000000FF00000000) | ((Source << 24) & 0x0000FF0000000000) | ((Source << 40) & 0x00FF000000000000) | ((Source << 56) & 0xFF00000000000000)); } ================================================ FILE: xtoskrnl/rtl/exports.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/exports.cc * DESCRIPTION: C-compatible API wrappers for exported kernel functions * DEVELOPERS: Aiken Harris */ #include /** * Clears all bits in the bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @return This routine does not return any value. * * @since NT 3.5 */ XTCLINK XTAPI VOID RtlClearAllBits(IN PRTL_BITMAP BitMap) { RTL::BitMap::ClearAllBits(BitMap); } /** * Clears a single bit in the bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @param Bit * Specifies the number of the bit to be cleared. * * @return This routine does not return any value. * * @since NT 5.1 */ XTCLINK XTAPI VOID RtlClearBit(IN PRTL_BITMAP BitMap, IN ULONG_PTR Bit) { RTL::BitMap::ClearBit(BitMap, Bit); } /** * Clears a specified set of bits within a bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @param StartingIndex * Supplies the starting index of the first bit to clear. * * @param Length * Supplies the length (number of bits) to clear. * * @return This routine does not return any value. * * @since NT 3.5 */ XTCLINK XTAPI VOID RtlClearBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR StartingIndex, IN ULONG_PTR Length) { RTL::BitMap::ClearBits(BitMap, StartingIndex, Length); } /** * Searches the bit map for a contiguous region of set bits and clears them. * * @param BitMap * Supplies a pointer to the bit map. * * @param Length * Supplies the length of contiguous region (number of set bits) to look for. * * @param Index * Supplies the index of the first bit to start the search at a given position. * * @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found. * * @since XT 1.0 */ XTCLINK XTAPI ULONG RtlClearSetBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index) { return RTL::BitMap::ClearSetBits(BitMap, Length, Index); } /** * Compares two GUIDs (Globally Unique Identifiers). * * @param Guid1 * Supplies the first GUID to compare. * * @param Guid2 * Supplies the second GUID to compare. * * @return This routine returns TRUE if the provided GUIDs are equal, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN RtlCompareGuids(IN PGUID Guid1, IN PGUID Guid2) { return RTL::Guid::CompareGuids(Guid1, Guid2); } /** * This routine compares the first bytes of the specified memory buffers. * * @param LeftBuffer * Supplies a pointer to the first block of memory to compare. * * @param RightBuffer * Supplies a pointer to the second block of memory to compare. * * @param Length * Specifies a number of bytes to compare. * * @return This routine returns a number of bytes that are equal in both memory blocks. * * @since NT 3.5 */ XTCLINK XTAPI SIZE_T RtlCompareMemory(IN PCVOID LeftBuffer, IN PCVOID RightBuffer, IN SIZE_T Length) { return RTL::Memory::CompareMemory(LeftBuffer, RightBuffer, Length); } /** * Compares at most specified number of characters of two C strings. * * @param String1 * String to be compared. * * @param String2 * String to be compared. * * @param Length * Maximum number of characters to compare. If no limit set, it compares whole strings. * * @return Integral value indicating the relationship between the strings. * * @since XT 1.0 */ XTCLINK XTAPI SIZE_T RtlCompareString(IN PCSTR String1, IN PCSTR String2, IN SIZE_T Length) { return RTL::String::CompareString(String1, String2, Length); } /** * Compares at most specified number of characters of two C strings, while ignoring differences in case. * * @param String1 * String to be compared. * * @param String2 * String to be compared. * * @param Length * Maximum number of characters to compare. If no limit set, it compares whole strings. * * @return Integral value indicating the relationship between the strings. * * @since XT 1.0 */ XTCLINK XTAPI SIZE_T RtlCompareStringInsensitive(IN PCSTR String1, IN PCSTR String2, IN SIZE_T Length) { return RTL::String::CompareStringInsensitive(String1, String2, Length); } /** * Compares at most specified number of characters of two C wide strings. * * @param String1 * Wide string to be compared. * * @param String2 * Wide string to be compared. * * @param Length * Maximum number of characters to compare. If no limit set, it compares whole wide strings. * * @return Integral value indicating the relationship between the wide strings. * * @since XT 1.0 */ XTCLINK XTAPI SIZE_T RtlCompareWideString(IN PCWSTR String1, IN PCWSTR String2, IN SIZE_T Length) { return RTL::WideString::CompareWideString(String1, String2, Length); } /** * Compares at most specified number of characters of two C wide strings, while ignoring differences in case. * * @param String1 * Wide string to be compared. * * @param String2 * Wide string to be compared. * * @param Length * Maximum number of characters to compare. If no limit set, it compares whole wide strings. * * @return Integral value indicating the relationship between the wide strings. * * @since XT 1.0 */ XTCLINK XTAPI SIZE_T RtlCompareWideStringInsensitive(IN PCWSTR String1, IN PCWSTR String2, IN SIZE_T Length) { return RTL::WideString::CompareWideStringInsensitive(String1, String2, Length); } /** * Appends a copy of the source string to the end of the destination string. * * @param Destination * Supplies a pointer to the NULL-terminated string to append to. * * @param Source * Supplies a pointer to the NULL-terminated string to copy from. * * @param Count * Sets a maximum number of characters to copy. If no limit set, appends whole string. * * @return This routine returns a copy of a destination string. * * @since XT 1.0 */ XTCLINK XTAPI PCHAR RtlConcatenateString(OUT PCHAR Destination, IN PCHAR Source, IN SIZE_T Count) { return RTL::String::ConcatenateString(Destination, Source, Count); } /** * Appends a copy of the source wide string to the end of the destination wide string. * * @param Destination * Supplies a pointer to the NULL-terminated wide string to append to. * * @param Source * Supplies a pointer to the NULL-terminated wide string to copy from. * * @param Count * Sets a maximum number of wide characters to copy. If no limit set, appends whole wide string. * * @return This routine returns a copy of a destination wide string. * * @since XT 1.0 */ XTCLINK XTAPI PWCHAR RtlConcatenateWideString(OUT PWCHAR Destination, IN PWCHAR Source, IN SIZE_T Count) { return RTL::WideString::ConcatenateWideString(Destination, Source, Count); } /** * Converts the 32-bit signed value to a large integer. * * @param Value * Supplies the value to convert. * * @return This routine returns the large integer representation of the given value. * * @since XT 1.0 */ XTCLINK XTAPI LARGE_INTEGER RtlConvertToLargeInteger32(IN LONG Value) { return RTL::Math::ConvertToLargeInteger32(Value); } /** * Converts the 32-bit unsigned value to a large integer. * * @param Value * Supplies the value to convert. * * @return This routine returns the large integer representation of the given value. * * @since XT 1.0 */ XTCLINK XTAPI LARGE_INTEGER RtlConvertToLargeIntegerUnsigned32(IN ULONG Value) { return RTL::Math::ConvertToLargeIntegerUnsigned32(Value); } /** * This routine copies a block of memory. * * @param Destination * Supplies a pointer to the buffer where data will be copied to. * * @param Source * Supplies a pointer to the source buffer that will be copied. * * @param Length * Specifies the number of bytes to copy. * * @return This routine does not return any value. * * @since NT 3.5 */ XTCLINK XTAPI VOID RtlCopyMemory(OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length) { RTL::Memory::CopyMemory(Destination, Source, Length); } /** * Copies a string from a buffer into another buffer, ensuring that the destination string is NULL-terminated. * * @param Destination * Supplies a pointer to the destination buffer. * * @param Source * Supplies a pointer to the source buffer. * * @param Length * Supplies the length of the string to copy. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID RtlCopyString(IN PCHAR Destination, IN PCSTR Source, IN ULONG Length) { RTL::String::CopyString(Destination, Source, Length); } /** * Copies a wide string from a buffer into another buffer, ensuring that the destination string is NULL-terminated. * * @param Destination * Supplies a pointer to the destination buffer. * * @param Source * Supplies a pointer to the source buffer. * * @param Length * Supplies the length of the wide string to copy. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID RtlCopyWideString(IN PWCHAR Destination, IN PCWSTR Source, IN ULONG Length) { RTL::WideString::CopyWideString(Destination, Source, Length); } /** * Divides a signed large integer by a 32-bit divisor. * * @param Dividend * Supplies a large integer to be divided. * * @param Divisor * Supplies a 32-bit divisor. * * @param Remainder * Supplies a pointer that receives the divide remainder. * * @return This routine returns the quotient. * * @since XT 1.0 */ XTCLINK XTAPI LARGE_INTEGER RtlDivideLargeInteger(IN LARGE_INTEGER Dividend, IN ULONG Divisor, OUT PULONG Remainder) { return RTL::Math::DivideLargeInteger(Dividend, Divisor, Remainder); } /** * Searches the bit map for a contiguous region of clear bits. * * @param BitMap * Supplies a pointer to the bit map. * * @param Length * Supplies the length of contiguous region (number of clear bits) to look for. * * @param Index * Supplies the index of the first bit to start the search at a given position. * * @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found. * * @since NT 3.5 */ XTCLINK XTAPI ULONG_PTR RtlFindClearBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index) { return RTL::BitMap::FindClearBits(BitMap, Length, Index); } /** * Searches the bit map for a contiguous region of set bits. * * @param BitMap * Supplies a pointer to the bit map. * * @param Length * Supplies the length of contiguous region (number of set bits) to look for. * * @param Index * Supplies the index of the first bit to start the search at a given position. * * @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found. * * @since NT 3.5 */ XTCLINK XTAPI ULONG_PTR RtlFindSetBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index) { return RTL::BitMap::FindSetBits(BitMap, Length, Index); } /** * Finds the first occurrence of the search string in the source string. * * @param Source * Supplies a pointer to the source string. * * @param Search * Supplies a pointer to the search string. * * @return This routine returns a pointer to the first occurrence of the search string in the source string. * * @since XT 1.0 */ XTCLINK XTAPI PCSTR RtlFindString(IN PCSTR Source, IN PCSTR Search) { return RTL::String::FindString(Source, Search); } /** * Finds the first case-insensitive occurrence of the search string in the source string. * * @param Source * Supplies a pointer to the source string. * * @param Search * Supplies a pointer to the search string. * * @return This routine returns a pointer to the first occurrence of the search string in the source string. * * @since XT 1.0 */ XTCLINK XTAPI PCSTR RtlFindStringInsensitive(IN PCSTR Source, IN PCSTR Search) { return RTL::String::FindStringInsensitive(Source, Search); } /** * Finds the first occurrence of the search wide string in the source wide string. * * @param Source * Supplies a pointer to the source wide string. * * @param Search * Supplies a pointer to the search wide string. * * @return This routine returns a pointer to the first occurrence of the search wide string in the source wide string. * * @since XT 1.0 */ XTCLINK XTAPI PCWSTR RtlFindWideString(IN PCWSTR Source, IN PCWSTR Search) { return RTL::WideString::FindWideString(Source, Search); } /** * Finds the first case-insensitive occurrence of the search wide string in the source wide string. * * @param Source * Supplies a pointer to the source wide string. * * @param Search * Supplies a pointer to the search wide string. * * @return This routine returns a pointer to the first occurrence of the search wide string in the source wide string. * * @since XT 1.0 */ XTCLINK XTAPI PCWSTR RtlFindWideStringInsensitive(IN PCWSTR Source, IN PCWSTR Search) { return RTL::WideString::FindWideStringInsensitive(Source, Search); } /** * Initializes a bit map. * * @param BitMap * Supplies a pointer to the bit map to initialize. * * @param Buffer * Supplies a pointer to the buffer that will be used as a bit map. * * @param Size * Supplies a size of the bit map. * * @return This routine does not return any value. * * @since NT 3.5 */ XTCLINK XTAPI VOID RtlInitializeBitMap(IN PRTL_BITMAP BitMap, IN PULONG_PTR Buffer, IN ULONG Size) { RTL::BitMap::InitializeBitMap(BitMap, Buffer, Size); } /** * This routine initializes a structure representing the head of a double-linked list. * * @param ListHead * Pointer to a structure that serves as the list header. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTCDECL VOID RtlInitializeListHead(IN PLIST_ENTRY ListHead) { RTL::LinkedList::InitializeListHead(ListHead); } /** * This routine inserts an entry at the head of a doubly linked list. * * @param ListHead * Pointer to the head of the list. * * @param Entry * Pointer to the entry that will be inserted in the list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTCDECL VOID RtlInsertHeadList(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry) { RTL::LinkedList::InsertHeadList(ListHead, Entry); } /** * This routine inserts an entry at the tail of a doubly linked list. * * @param ListHead * Pointer to the head of the list. * * @param Entry * Pointer to the entry that will be inserted in the list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTCDECL VOID RtlInsertTailList(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry) { RTL::LinkedList::InsertTailList(ListHead, Entry); } /** * Indicates whether a doubly linked list structure is empty, or not initialized at all. * * @param ListHead * Pointer to a structure that represents the head of the list. * * @return TRUE if there are currently no entries in the list or FALSE otherwise. * * @since XT 1.0 */ XTCLINK XTCDECL BOOLEAN RtlListEmpty(IN PLIST_ENTRY ListHead) { return RTL::LinkedList::ListEmpty(ListHead); } /** * This routine detects a loop in a doubly linked list. * * @param ListHead * Pointer to a structure that represents the head of the list. * * @return TRUE if linked list contains a loop or FALSE otherwise. * * @since XT 1.0 */ XTCLINK XTCDECL BOOLEAN RtlListLoop(IN PLIST_ENTRY ListHead) { return RTL::LinkedList::ListLoop(ListHead); } /** * This routine copies a block of memory either forward of backward, depeding * if source and destination buffers overlap or not. * * @param Destination * Supplies a pointer to the buffer where data will be copied to. * * @param Source * Supplies a pointer to the source buffer that will be copied. * * @param Length * Specifies the number of bytes to copy. * * @return This routine does not return any value. * * @since NT 3.5 */ XTCLINK XTAPI VOID RtlMoveMemory(OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length) { RTL::Memory::MoveMemory(Destination, Source, Length); } /** * Multiplies a signed large integer by a signed integer. * * @param Multiplicand * Supplies a large integer to be multiplied. * * @param Multiplier * Supplies an integer by which the large integer is multiplied. * * @return This routine returns the result of the multiplication. * * @since XT 1.0 */ XTCLINK XTAPI LARGE_INTEGER RtlMultiplyLargeInteger(IN LARGE_INTEGER Multiplicand, IN LONG Multiplier) { return RTL::Math::MultiplyLargeInteger(Multiplicand, Multiplier); } /** * This routine removes an entry from a doubly linked list. * * @param Entry * Pointer to the entry that will be removed from the list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTCDECL VOID RtlRemoveEntryList(IN PLIST_ENTRY Entry) { RTL::LinkedList::RemoveEntryList(Entry); } /** * Reverses a characters order in a string. It modifies the original, input variable. * * @param String * Supplies a pointer to the string to reverse. * * @param Length * Supplies the length of the string to reverse. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID RtlReverseString(IN OUT PCHAR String, IN ULONG Length) { RTL::String::ReverseString(String, Length); } /** * Reverses a characters order in a wide string. It modifies the original, input variable. * * @param String * Supplies a pointer to the wide string to reverse. * * @param Length * Supplies the length of the wide string to reverse. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID RtlReverseWideString(IN OUT PWCHAR String, IN ULONG Length) { RTL::WideString::ReverseWideString(String, Length); } /** * This routine compares the first bytes of the specified memory buffers. * * @param LeftBuffer * Supplies a pointer to the first block of memory to compare. * * @param RightBuffer * Supplies a pointer to the second block of memory to compare. * * @param Length * Specifies a number of bytes to compare. * * @return Returns TRUE if both buffers are equal up to the specified length, or FALSE otherwise. * * @since XT 1.0 */ XTCLINK XTAPI BOOLEAN RtlSameMemory(IN PCVOID LeftBuffer, IN PCVOID RightBuffer, IN SIZE_T Length) { return RTL::Memory::SameMemory(LeftBuffer, RightBuffer, Length); } /** * Sets all bits in the bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @return This routine does not return any value. * * @since NT 3.5 */ XTCLINK XTAPI VOID RtlSetAllBits(IN PRTL_BITMAP BitMap) { RTL::BitMap::SetAllBits(BitMap); } /** * Sets a single bit in the bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @param Bit * Specifies the number of the bit to be set. * * @return This routine does not return any value. * * @since NT 5.1 */ XTCLINK XTAPI VOID RtlSetBit(IN PRTL_BITMAP BitMap, IN ULONG_PTR Bit) { RTL::BitMap::SetBit(BitMap, Bit); } /** * Sets a specified set of bits within a bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @param StartingIndex * Supplies the starting index of the first bit to set. * * @param Length * Supplies the length (number of bits) to set. * * @return This routine does not return any value. * * @since NT 3.5 */ XTCLINK XTAPI VOID RtlSetBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR StartingIndex, IN ULONG_PTR Length) { RTL::BitMap::SetBits(BitMap, StartingIndex, Length); } /** * Searches the bit map for a contiguous region of clear bits and sets them. * * @param BitMap * Supplies a pointer to the bit map. * * @param Length * Supplies the length of contiguous region (number of clear bits) to look for. * * @param Index * Supplies the index of the first bit to start the search at a given position. * * @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found. * * @since XT 1.0 */ XTCLINK XTAPI ULONG RtlSetClearBits(IN PRTL_BITMAP BitMap, IN ULONG_PTR Length, IN ULONG_PTR Index) { return RTL::BitMap::SetClearBits(BitMap, Length, Index); } /** * This routine fills a section of memory with a specified byte. * * @param Destination * Supplies a pointer to the buffer to fill. * * @param Byte * Supplies a pattern to fill memory. * * @param Length * Specifies a number of bytes to store in memory. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCLINK XTAPI VOID RtlSetMemory(OUT PVOID Destination, IN UCHAR Byte, IN SIZE_T Length) { RTL::Memory::SetMemory(Destination, Byte, Length); } /** * Calculates the length of a given string. * * @param String * Pointer to the NULL-terminated string to be examined. * * @param MaxLength * Maximum number of characters to examine. If no limit set, it examines whole string. * * @return The length of the NULL-terminated string. * * @since: XT 1.0 */ XTCLINK XTAPI SIZE_T RtlStringLength(IN PCSTR String, IN SIZE_T MaxLength) { return RTL::String::StringLength(String, MaxLength); } /** * Converts a multibyte character string to its wide character representation. * * @param Destination * Pointer to wide character array where the wide string will be stored * * @param Source * Pointer to the first element of a multibyte string to convert. * * @param Length * Number of characters in the source string. * * @return Returns the number of wide characters written to the destination array on success, or -1 on error. * * @since XT 1.0 */ XTCLINK XTAPI SIZE_T RtlStringToWideString(OUT PWCHAR Destination, IN PCSTR *Source, IN SIZE_T Length) { return RTL::String::StringToWideString(Destination, Source, Length); } /** * Tests a state of a single bit in the bit map. * * @param BitMap * Supplies a pointer to the bit map. * * @param Bit * Specifies the number of the bit to be tested. * * @return This routine returns TRUE when bit is set, or FALSE otherwise. * * @since NT 5.1 */ XTCLINK XTAPI BOOLEAN RtlTestBit(IN PRTL_BITMAP BitMap, IN ULONG_PTR Bit) { return RTL::BitMap::TestBit(BitMap, Bit); } /** * Converts a TIME_FIELDS calendar structure to a 64-bit Unix timestamp. * * @param TimeFields * Supplies a pointer to a fully populated TIME_FIELDS structure. * * @param UnixTime * Supplies a pointer to a 64-bit integer that receives the number of * seconds elapsed since January 1, 1970. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCLINK XTAPI XTSTATUS RtlTimeFieldsToUnixEpoch(IN PTIME_FIELDS TimeFields, OUT PLONGLONG UnixTime) { return RTL::Time::TimeFieldsToUnixEpoch(TimeFields, UnixTime); } /** * Converts a TIME_FIELDS calendar structure to a 64-bit XT timestamp. * * @param TimeFields * Supplies a pointer to a fully populated TIME_FIELDS structure. * * @param Time * Supplies a pointer to variable that receives the converted time value in 100-nanosecond * intervals since January 1, 1601. * * @return This routine returns the status code. * * @since XT 1.0 */ XTCLINK XTAPI XTSTATUS RtlTimeFieldsToXtEpoch(IN PTIME_FIELDS TimeFields, OUT PLARGE_INTEGER XtTime) { return RTL::Time::TimeFieldsToXtEpoch(TimeFields, XtTime); } /** * Finds the next token in a NULL-terminated string. * * @param String * Pointer to the NULL-terminated string to tokenize. * * @param Delimiter * Pointer to the NULL-terminated string identifying delimiters. * * @param SavePtr * Pointer to an object used to store routine internal state. * * @return Pointer to the beginning of the next token or NULL if there are no more tokens. * * @since: XT 1.0 */ XTCLINK XTAPI PCHAR RtlTokenizeString(IN PCHAR String, IN PCSTR Delimiter, IN OUT PCHAR *SavePtr) { return RTL::String::TokenizeString(String, Delimiter, SavePtr); } /** * Finds the next token in a NULL-terminated wide string. * * @param String * Pointer to the NULL-terminated wide string to tokenize. * * @param Delimiter * Pointer to the NULL-terminated wide string identifying delimiters. * * @param SavePtr * Pointer to an object used to store routine internal state. * * @return Pointer to the beginning of the next token or NULLPTR if there are no more tokens. * * @since: XT 1.0 */ XTCLINK XTAPI PWCHAR RtlTokenizeWideString(IN PWCHAR String, IN PCWSTR Delimiter, IN OUT PWCHAR *SavePtr) { return RTL::WideString::TokenizeWideString(String, Delimiter, SavePtr); } /** * Converts a character to lowercase. * * @param Character * Character to be converted. * * @return Converted character or original character if it was not uppercase. * * @since XT 1.0 */ XTCLINK XTAPI CHAR RtlToLowerCharacter(IN CHAR Character) { return RTL::String::ToLowerCharacter(Character); } /** * Converts a wide character to lowercase. * * @param Character * Wide character to be converted. * * @return Converted wide character or original character if it was not uppercase. * * @since XT 1.0 */ XTCLINK XTAPI WCHAR RtlToLowerWideCharacter(IN WCHAR Character) { return RTL::WideString::ToLowerWideCharacter(Character); } /** * Converts a character to uppercase. * * @param Character * Character to be converted. * * @return Converted character or original character if it was not lowercase. * * @since XT 1.0 */ XTCLINK XTAPI CHAR RtlToUpperCharacter(IN CHAR Character) { return RTL::String::ToUpperCharacter(Character); } /** * Converts a wide character to uppercase. * * @param Character * Wide character to be converted. * * @return Converted wide character or original character if it was not lowercase. * * @since XT 1.0 */ XTCLINK XTAPI WCHAR RtlToUpperWideCharacter(IN WCHAR Character) { return RTL::WideString::ToUpperWideCharacter(Character); } /** * Removes certain characters from a beginning of the string. * * @param String * Pointer to the NULL-terminated string to be trimmed. * * @return This routine returns a pointer to the left-trimmed string. * * @since XT 1.0 */ XTCLINK XTAPI PCHAR RtlTrimLeftString(IN PCHAR String) { return RTL::String::TrimLeftString(String); } /** * Removes certain characters from a beginning of the wide string. * * @param String * Pointer to the NULL-terminated wide string to be trimmed. * * @return This routine returns a pointer to the left-trimmed wide string. * * @since XT 1.0 */ XTCLINK XTAPI PWCHAR RtlTrimLeftWideString(IN PWCHAR String) { return RTL::WideString::TrimLeftWideString(String); } /** * Removes certain characters from the end of the string. * * @param String * Pointer to the NULL-terminated string to be trimmed. * * @return This routine returns a pointer to the right-trimmed string. * * @since XT 1.0 */ XTCLINK XTAPI PCHAR RtlTrimRightString(IN PCHAR String) { return RTL::String::TrimRightString(String); } /** * Removes certain characters from the end of the wide string. * * @param String * Pointer to the NULL-terminated wide string to be trimmed. * * @return This routine returns a pointer to the right-trimmed wide string. * * @since XT 1.0 */ XTCLINK XTAPI PWCHAR RtlTrimRightWideString(IN PWCHAR String) { return RTL::WideString::TrimRightWideString(String); } /** * Removes certain characters from the beginning and the end of the string. * * @param String * Pointer to the NULL-terminated string to be trimmed. * * @return This routine returns a pointer to the trimmed string. * * @since XT 1.0 */ XTCLINK XTAPI PCHAR RtlTrimString(IN PCHAR String) { return RTL::String::TrimLeftString(RTL::String::TrimRightString(String)); } /** * Removes certain characters from the beginning and the end of the wide string. * * @param String * Pointer to the NULL-terminated wide string to be trimmed. * * @return This routine returns a pointer to the trimmed wide string. * * @since XT 1.0 */ XTCLINK XTAPI PWCHAR RtlTrimWideString(IN PWCHAR String) { return RTL::WideString::TrimWideString(String); } /** * Calculates the length of a given wide string. * * @param String * Pointer to the NULL-terminated wide string to be examined. * * @param MaxLength * Maximum number of wide characters to examine. If no limit set, it examines whole string. * * @return The length of the NULL-terminated wide string. * * @since: XT 1.0 */ XTCLINK XTAPI SIZE_T RtlWideStringLength(IN PCWSTR String, IN SIZE_T MaxLength) { return RTL::WideString::WideStringLength(String, MaxLength); } /** * This routine fills a section of memory with zeroes. * * @param Destination * Supplies a pointer to the buffer to fill. * * @param Length * Specifies a number of bytes to be filled with zeroes. * * @return This routine does not return any value. * * @since NT 3.5 */ XTCLINK XTAPI VOID RtlZeroMemory(OUT PVOID Destination, IN SIZE_T Length) { RTL::Memory::ZeroMemory(Destination, Length); } ================================================ FILE: xtoskrnl/rtl/guid.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/guid.cc * DESCRIPTION: GUID manipulation routines * DEVELOPERS: Rafal Kupiec */ #include /** * Compares two GUIDs (Globally Unique Identifiers). * * @param Guid1 * Supplies the first GUID to compare. * * @param Guid2 * Supplies the second GUID to compare. * * @return This routine returns TRUE if the provided GUIDs are equal, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN RTL::Guid::CompareGuids(IN PGUID Guid1, IN PGUID Guid2) { PUINT Guid1Ptr, Guid2Ptr; /* Cast GUIDs to UINT to compare 32-bits at a time */ Guid1Ptr = (PUINT)Guid1; Guid2Ptr = (PUINT)Guid2; /* Compare GUIDs */ return (Guid1Ptr[0] == Guid2Ptr[0] && Guid1Ptr[1] == Guid2Ptr[1] && Guid1Ptr[2] == Guid2Ptr[2] && Guid1Ptr[3] == Guid2Ptr[3]); } ================================================ FILE: xtoskrnl/rtl/i686/dispatch.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/i686/dispatch.cc * DESCRIPTION: Dispatching support for i686 architecture * DEVELOPERS: Rafal Kupiec */ #include /** * Returns the stack limits for the current thread. * * @param StackBase * Supplies a pointer to memory area, where the stack base will be stored. * * @param StackLimit * Suppliws a pointer to memory area, where the stack limit will be stored. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID RTL::Dispatcher::GetStackLimits(OUT PULONG_PTR StackBase, OUT PULONG_PTR StackLimit) { PKTHREAD Thread = KE::Processor::GetCurrentThread(); *StackBase = (ULONG_PTR)Thread->StackBase - sizeof(FX_SAVE_AREA); *StackLimit = (ULONG_PTR)Thread->StackLimit; } ================================================ FILE: xtoskrnl/rtl/i686/exsup.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/i686/exsup.cc * DESCRIPTION: Exception handling for i686 architecture * DEVELOPERS: Rafal Kupiec * Aiken Harris */ #include /** * Handles SEH structured exception frames. * * @param ExceptionRecord * A pointer to the exception record. * * @param EstablisherFrame * The address of the base of the fixed stack allocation. * * @param ContextRecord * A pointer to the context record at the time the exception was raised. * * @param DispatcherContext * A pointer to the dispatcher context for the function. * * @return This routine returns an exception disposition value if the exception was not handled by any filter. * * @since XT 1.0 */ XTCLINK XTCDECL EXCEPTION_DISPOSITION __C_specific_handler(IN PEXCEPTION_RECORD ExceptionRecord, IN PVOID EstablisherFrame, IN OUT PCONTEXT ContextRecord, IN OUT PVOID DispatcherContext) { UNIMPLEMENTED; /* Continue execution */ return ExceptionContinueExecution; } /** * Handles C++ structured exception frames. This implementation displays a panic screen and halts the system. * * @param ExceptionRecord * A pointer to the exception record that is passed to the possible catch statements. * * @param EstablisherFrame * A pointer to the stack frame that is used to handle the exception. * * @param ContextRecord * A pointer to the context record (not used on Intel CPUs). * * @param DispatcherContext * A pointer to the dispatcher provding information about function entry and stack frame (not used on Intel CPUs). * * @return This routine returns an exception disposition value if the exception was not handled by any filter. * * @since XT 1.0 */ XTCLINK XTCDECL EXCEPTION_DISPOSITION __CxxFrameHandler3(IN PEXCEPTION_RECORD ExceptionRecord, IN PVOID EstablisherFrame, IN OUT PCONTEXT ContextRecord, IN OUT PVOID DispatcherContext) { UNIMPLEMENTED; /* Disable interrupts and hang */ AR::CpuFunctions::ClearInterruptFlag(); KE::Crash::Panic(0); /* Continue search */ return ExceptionContinueSearch; } /** * Finds the appropriate exception handler to process the current exception. * * @param ExceptionRecord * A pointer to the exception record providing information about the specific exception. * * @param Registration * A pointer to the record that indicates which scope table should be used to find the exception handler. * * @param Context * Reserved. * * @param Dispatcher * Reserved. * * @return This routine returns DISPOSITION_DISMISS or DISPOSITION_CONTINUE_SEARCH. * * @since XT 1.0 */ XTCLINK XTCDECL INT _except_handler3(IN PEXCEPTION_RECORD ExceptionRecord, IN PVOID Registration, IN PCONTEXT Context, IN PVOID Dispatcher) { UNIMPLEMENTED; /* Handler not found */ return 0; } /** * Handles pure virtual function call error. This implementation displays a panic screen and halts the system. * * @return This function does not return any value. * * @since XT 1.0 */ XTCLINK XTCDECL VOID _purecall(VOID) { UNIMPLEMENTED; /* Disable interrupts and hang */ AR::CpuFunctions::ClearInterruptFlag(); KE::Crash::Panic(0); } ================================================ FILE: xtoskrnl/rtl/i686/intrin.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/i686/intrin.cc * DESCRIPTION: Compiler intrinsic support routines * DEVELOPERS: Aiken Harris */ #include /** * Divides a 64-bit signed integer by a 64-bit signed integer. * * @param Dividend * Supplies the 64-bit signed dividend. * * @param Divisor * Supplies the 64-bit signed divisor. * * @return This routine returns the 64-bit signed quotient. * * @since XT 1.0 */ XTCLINK XTAPI LONGLONG _alldiv(IN LONGLONG Dividend, IN LONGLONG Divisor) { /* Call the internal signed division routine and return the quotient */ return RTL::Math::Divide64(Dividend, Divisor, NULLPTR); } /** * Divides a 64-bit signed integer by a 64-bit signed integer and retrieves the remainder. * * @param Dividend * Supplies the 64-bit signed dividend. * * @param Divisor * Supplies the 64-bit signed divisor. * * @param Remainder * Supplies a pointer to a variable that receives the 64-bit signed remainder. * * @return This routine returns the 64-bit signed quotient. * * @since XT 1.0 */ XTCLINK XTAPI LONGLONG _alldvrm(IN LONGLONG Dividend, IN LONGLONG Divisor, OUT PLONGLONG Remainder) { /* Call the internal signed division routine to compute both quotient and remainder */ return RTL::Math::Divide64(Dividend, Divisor, Remainder); } /** * Calculates the remainder of a 64-bit signed integer division. * * @param Dividend * Supplies the 64-bit signed dividend. * * @param Divisor * Supplies the 64-bit signed divisor. * * @return This routine returns the 64-bit signed remainder. * * @since XT 1.0 */ XTCLINK XTAPI LONGLONG _allrem(IN LONGLONG Dividend, IN LONGLONG Divisor) { LONGLONG Remainder; /* Call the internal signed division routine and return the computed remainder */ RTL::Math::Divide64(Dividend, Divisor, &Remainder); return Remainder; } /** * Divides a 64-bit unsigned integer by a 64-bit unsigned integer. * * @param Dividend * Supplies the 64-bit unsigned dividend. * * @param Divisor * Supplies the 64-bit unsigned divisor. * * @return This routine returns the 64-bit unsigned quotient. * * @since XT 1.0 */ XTCLINK XTAPI ULONGLONG _aulldiv(IN ULONGLONG Dividend, IN ULONGLONG Divisor) { /* Call the internal unsigned division routine and return the quotient */ return RTL::Math::DivideUnsigned64(Dividend, Divisor, NULLPTR); } /** * Divides a 64-bit unsigned integer by a 64-bit unsigned integer and retrieves the remainder. * * @param Dividend * Supplies the 64-bit unsigned dividend. * * @param Divisor * Supplies the 64-bit unsigned divisor. * * @param Remainder * Supplies a pointer to a variable that receives the 64-bit unsigned remainder. * * @return This routine returns the 64-bit unsigned quotient. * * @since XT 1.0 */ XTCLINK XTAPI ULONGLONG _aulldvrm(IN ULONGLONG Dividend, IN ULONGLONG Divisor, OUT PULONGLONG Remainder) { /* Call the internal unsigned division routine to compute both quotient and remainder */ return RTL::Math::DivideUnsigned64(Dividend, Divisor, Remainder); } /** * Calculates the remainder of a 64-bit unsigned integer division. * * @param Dividend * Supplies the 64-bit unsigned dividend. * * @param Divisor * Supplies the 64-bit unsigned divisor. * * @return This routine returns the 64-bit unsigned remainder. * * @since XT 1.0 */ XTCLINK XTAPI ULONGLONG _aullrem(IN ULONGLONG Dividend, IN ULONGLONG Divisor) { ULONGLONG Remainder; /* Call the internal unsigned division routine and return the computed remainder */ RTL::Math::DivideUnsigned64(Dividend, Divisor, &Remainder); return Remainder; } ================================================ FILE: xtoskrnl/rtl/llist.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/llist.cc * DESCRIPTION: Doubly linked list manipulation routines * DEVELOPERS: Rafal Kupiec */ #include /** * Retrieves the first entry from a doubly linked list without removing it from the list. * * @param ListHead * Supplies a pointer to a structure that serves as the list header. * * @return This routine returns a pointer to the first entry in the list, or NULLPTR if the list is empty. * * @since XT 1.0 */ XTCDECL PLIST_ENTRY RTL::LinkedList::GetFirstEntry(IN PLIST_ENTRY ListHead) { /* Check if the list is empty */ if(ListEmpty(ListHead)) { /* Empty list, return NULLPTR */ return NULLPTR; } /* Return first entry in the list */ return ListHead->Flink; } /** * Initializes a structure representing the head of a doubly linked list. * * @param ListHead * Supplies a pointer to a structure that serves as the list header. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::LinkedList::InitializeListHead(IN PLIST_ENTRY ListHead) { /* Initialize list head */ ListHead->Blink = ListHead; ListHead->Flink = ListHead; } /** * Initializes a structure representing the head of a 32bit doubly linked list. * * @param ListHead * Supplies a pointer to a structure that serves as the list header. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::LinkedList::InitializeListHead32(IN PLIST_ENTRY32 ListHead) { /* Initialize list head */ ListHead->Blink = PtrToUlong(ListHead); ListHead->Flink = PtrToUlong(ListHead); } /** * Inserts an entry at the head of a doubly linked list. * * @param ListHead * Supplies a pointer to the head of the list. * * @param Entry * Supplies a pointer to the entry that will be inserted in the list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::LinkedList::InsertHeadList(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry) { /* Insert entry at the head of the list */ Entry->Flink = ListHead->Flink; Entry->Blink = ListHead; ListHead->Flink->Blink = Entry; ListHead->Flink = Entry; } /** * Inserts an entry at the tail of a doubly linked list. * * @param ListHead * Supplies a pointer to the head of the list. * * @param Entry * Supplies a pointer to the entry that will be inserted in the list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::LinkedList::InsertTailList(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry) { /* Insert entry at the tail of the list */ Entry->Flink = ListHead; Entry->Blink = ListHead->Blink; ListHead->Blink->Flink = Entry; ListHead->Blink = Entry; } /** * Indicates whether a doubly linked list structure is empty, or not initialized at all. * * @param ListHead * Supplies a pointer to a structure that represents the head of the list. * * @return This routine returns TRUE if there are currently no entries in the list or FALSE otherwise. * * @since XT 1.0 */ XTCDECL BOOLEAN RTL::LinkedList::ListEmpty(IN PLIST_ENTRY ListHead) { /* Check if the list is empty */ return (((ListHead->Flink == NULLPTR) && (ListHead->Blink == NULLPTR)) || (ListHead->Flink == ListHead)); } /** * Detects a loop in a doubly linked list. * * @param ListHead * Supplies a pointer to a structure that represents the head of the list. * * @return TRUE if linked list contains a loop or FALSE otherwise. * * @since XT 1.0 */ XTCDECL BOOLEAN RTL::LinkedList::ListLoop(IN PLIST_ENTRY ListHead) { PLIST_ENTRY SlowEntry, FastEntry; /* Check if list exists */ if(ListHead == NULLPTR) { /* No loop in non-existen list */ return FALSE; } /* Make both references pointing to the start of the list */ FastEntry = ListHead; SlowEntry = ListHead; /* Iterate through the linked list to find a loop */ while(SlowEntry != NULLPTR && FastEntry != NULLPTR && FastEntry->Flink != NULLPTR) { /* Move slow and fast pointers by one and two positions accordingly */ SlowEntry = SlowEntry->Flink; FastEntry = FastEntry->Flink->Flink; /* Compare both pointers */ if(SlowEntry == FastEntry) { /* Loop found */ return TRUE; } } /* No loop found */ return FALSE; } /** * Removes an entry from a doubly linked list. * * @param Entry * Supplies a pointer to the entry that will be removed from the list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::LinkedList::RemoveEntryList(IN PLIST_ENTRY Entry) { /* Remove entry from the list */ Entry->Flink->Blink = Entry->Blink; Entry->Blink->Flink = Entry->Flink; } /** * Splices a doubly linked list at the head of another list. The source list is reinitialized to empty. * * @param ListHead * Supplies a pointer to a structure that represents the head of the list. * * @param SpliceList * Supplies a pointer to a structure that represents the head of the list that will be spliced. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::LinkedList::SpliceHeadList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY SpliceList) { PLIST_ENTRY FirstEntry, LastEntry; /* Check if the list to splice is empty */ if(SpliceList->Flink == SpliceList) { /* Nothing to splice, return */ return; } /* Get first and last entries of the list to splice */ FirstEntry = SpliceList->Flink; LastEntry = SpliceList->Blink; /* Splice the list at the head of destination */ FirstEntry->Blink = ListHead; LastEntry->Flink = ListHead->Flink; ListHead->Flink->Blink = LastEntry; ListHead->Flink = FirstEntry; /* Reinitialize the source list to empty */ SpliceList->Blink = SpliceList; SpliceList->Flink = SpliceList; } /** * Splices a doubly linked list at the tail of another list. The source list is reinitialized to empty. * * @param ListHead * Supplies a pointer to the head of the destination list. * * @param SpliceList * Supplies a pointer to the head of the list that will be spliced. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::LinkedList::SpliceTailList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY SpliceList) { PLIST_ENTRY FirstEntry, LastEntry; /* Check if the list to splice is empty */ if(SpliceList->Flink == SpliceList) { /* Nothing to splice, return */ return; } /* Get first and last entries of the list to splice */ FirstEntry = SpliceList->Flink; LastEntry = SpliceList->Blink; /* Splice the list at the tail of destination */ FirstEntry->Blink = ListHead->Blink; LastEntry->Flink = ListHead; ListHead->Blink->Flink = FirstEntry; ListHead->Blink = LastEntry; /* Reinitialize the source list to empty */ SpliceList->Blink = SpliceList; SpliceList->Flink = SpliceList; } ================================================ FILE: xtoskrnl/rtl/math.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/math.cc * DESCRIPTION: Kernel math support * DEVELOPERS: Rafal Kupiec */ #include /** * Converts the 32-bit signed value to a large integer. * * @param Value * Supplies the value to convert. * * @return This routine returns the large integer representation of the given value. * * @since XT 1.0 */ XTAPI LARGE_INTEGER RTL::Math::ConvertToLargeInteger32(IN LONG Value) { LARGE_INTEGER LargeInt; /* Convert the value to a large integer and return it */ LargeInt.QuadPart = Value; return LargeInt; } /** * Converts the 32-bit unsigned value to a large integer. * * @param Value * Supplies the value to convert. * * @return This routine returns the large integer representation of the given value. * * @since XT 1.0 */ XTAPI LARGE_INTEGER RTL::Math::ConvertToLargeIntegerUnsigned32(IN ULONG Value) { LARGE_INTEGER LargeInt; /* Convert the value to a large integer and return it */ LargeInt.QuadPart = Value; return LargeInt; } /** * Determines the number of leading zero bits in a 32-bit unsigned value. * * @param Value * Supplies the value whose leading zero bits are to be counted. * * @return This routine returns the number of leading zero bits in the given value. * * @since XT 1.0 */ XTAPI INT RTL::Math::CountLeadingZeroes32(IN ULONG Value) { /* Return a number of leading zero bits */ return __builtin_clzl(Value); } /** * Determines the number of leading zero bits in a 64-bit unsigned value. * * @param Value * Supplies the value whose leading zero bits are to be counted. * * @return This routine returns the number of leading zero bits in the given value. * * @since XT 1.0 */ XTAPI INT RTL::Math::CountLeadingZeroes64(IN ULONGLONG Value) { /* Return a number of leading zero bits */ return __builtin_clzll(Value); } /** * Determines the number of trailing zero bits in a 32-bit unsigned value. * * @param Value * Supplies the value whose trailing zero bits are to be counted. * * @return This routine returns the number of trailing zero bits in the given value. * * @since XT 1.0 */ XTAPI INT RTL::Math::CountTrailingZeroes32(IN ULONG Value) { /* Return a number of trailing zero bits */ return __builtin_ctzl(Value); } /** * Determines the number of trailing zero bits in a 64-bit unsigned value. * * @param Value * Supplies the value whose trailing zero bits are to be counted. * * @return This routine returns the number of trailing zero bits in the given value. * * @since XT 1.0 */ XTAPI INT RTL::Math::CountTrailingZeroes64(IN ULONGLONG Value) { /* Return a number of trailing zero bits */ return __builtin_ctzll(Value); } /** * Performs a 32-bit divide operation on signed integer numbers. * * @param Dividend * Supplies a number that is going to be divided. * * @param Divisor * Supplies a number by which the dividend is divided. * * @param Remainder * Supplies a pointer that receives the divide remainder. * * @return This routine returns the quotient. * * @since XT 1.0 */ XTAPI LONGLONG RTL::Math::Divide32(IN LONG Dividend, IN LONG Divisor, OUT PLONG Remainder) { LONG Quotient; /* Calculate the quotient */ Quotient = Dividend / Divisor; /* Make sure a pointer to remainder provided */ if(Remainder) { /* Calculate remainder */ *Remainder = Dividend - (Quotient * Divisor); } /* Return the quotient */ return Quotient; } /** * Performs a 64-bit divide operation on signed integer numbers. * * @param Dividend * Supplies a number that is going to be divided. * * @param Divisor * Supplies a number by which the dividend is divided. * * @param Remainder * Supplies a pointer that receives the divide remainder. * * @return This routine returns the quotient. * * @since XT 1.0 */ XTAPI LONGLONG RTL::Math::Divide64(IN LONGLONG Dividend, IN LONGLONG Divisor, OUT PLONGLONG Remainder) { LONGLONG DividendSign, DivisorSign, Quotient, UDividend, UDivisor; /* Remove the sign bit from dividend and divisor if present */ DividendSign = Dividend >> ((sizeof(LONGLONG) * BITS_PER_BYTE) - 1); DivisorSign = Divisor >> ((sizeof(LONGLONG) * BITS_PER_BYTE) - 1); UDividend = (Dividend ^ DividendSign) - DividendSign; UDivisor = (Divisor ^ DivisorSign) - DivisorSign; /* Calculate the quotient */ DividendSign ^= DivisorSign; Quotient = (DivideUnsigned64(UDividend, UDivisor, NULLPTR) ^ DividendSign) - DividendSign; /* Make sure a pointer to remainder provided */ if(Remainder) { /* Calculate remainder */ *Remainder = Dividend - (Quotient * Divisor); } /* Return the quotient */ return Quotient; } /** * Performs a 32-bit divide operation on unsigned integer numbers. * * @param Dividend * Supplies an unsigned number that is going to be divided. * * @param Divisor * Supplies an unsigned number by which the dividend is divided. * * @param Remainder * Supplies a pointer that receives the unsigned divide remainder. * * @return This routine returns the quotient. * * @since XT 1.0 */ XTAPI ULONGLONG RTL::Math::DivideUnsigned32(IN ULONG Dividend, IN ULONG Divisor, OUT PULONG Remainder) { /* Make sure a pointer to remainder provided */ if(Remainder) { /* Calculate remainder */ *Remainder = Dividend % Divisor; } /* Return the quotient */ return Dividend / Divisor; } /** * Performs a 64-bit divide operation on unsigned integer numbers. * * @param Dividend * Supplies an unsigned number that is going to be divided. * * @param Divisor * Supplies an unsigned number by which the dividend is divided. * * @param Remainder * Supplies a pointer that receives the unsigned divide remainder. * * @return This routine returns the quotient. * * @since XT 1.0 */ XTAPI ULONGLONG RTL::Math::DivideUnsigned64(IN ULONGLONG Dividend, IN ULONGLONG Divisor, OUT PULONGLONG Remainder) { ULARGE_INTEGER DividendParts, DivisorParts, QuotientParts, RemainderParts; LONGLONG Difference; ULONGLONG Shift; ULONG Carry; /* Make sure divisor is not 0 */ if(Divisor == 0) { /* Cannot divide by 0 */ return 0; } /* Assign dividend and divisor to large integer representations */ DividendParts.QuadPart = Dividend; DivisorParts.QuadPart = Divisor; /* Check if dividend is 32-bit value */ if(DividendParts.u.HighPart == 0) { /* Check if devisor is 32-bit value */ if(DivisorParts.u.HighPart == 0) { /* 32-bit divide operation, check if remainder provided */ if(Remainder != NULLPTR) { /* Calculate remainder */ *Remainder = DividendParts.u.LowPart % DivisorParts.u.LowPart; } /* Return the quotient */ return DividendParts.u.LowPart / DivisorParts.u.LowPart; } /* 32-bit value divided by a 64-bit value, check if remainder provided */ if(Remainder != NULLPTR) { /* Calculate remainder */ *Remainder = DividendParts.u.LowPart; } /* Return zero as quotient */ return 0; } /* Dividend is a 64-bit value, check if divisor has a low part */ if(DivisorParts.u.LowPart != 0) { /* Divisor has a non-zero low part, check if divisor has a high part */ if(DivisorParts.u.HighPart != 0) { /* Divisor is 64-bit value, calculate the shift count */ Shift = CountLeadingZeroes32(DivisorParts.u.HighPart) - CountLeadingZeroes32(DividendParts.u.HighPart); /* Check if shift count exceeds 32-bits */ if(Shift > ((sizeof(ULONG) * BITS_PER_BYTE) - 1)) { /* Check if remainder provided */ if(Remainder != NULLPTR) { /* Calculate remainder */ *Remainder = DividendParts.QuadPart; } return 0; } /* Increase shift and clear quotient low part */ Shift++; QuotientParts.u.LowPart = 0; /* Check if shift is 32-bits */ if(Shift == (sizeof(ULONG) * BITS_PER_BYTE)) { /* Get the quotient high part and remainder */ QuotientParts.u.HighPart = DividendParts.u.LowPart; RemainderParts.u.LowPart = DividendParts.u.HighPart; RemainderParts.u.HighPart = 0; } else { /* Get the quotient high part and remainder */ QuotientParts.u.HighPart = DividendParts.u.LowPart << ((sizeof(ULONG) * BITS_PER_BYTE) - Shift); RemainderParts.u.LowPart = (DividendParts.u.HighPart << ((sizeof(ULONG) * BITS_PER_BYTE) - Shift)) | (DividendParts.u.LowPart >> Shift); RemainderParts.u.HighPart = DividendParts.u.HighPart >> Shift; } } else { /* Divisor is 32-bit value, calculate the shift count */ Shift = (sizeof(ULONG) * BITS_PER_BYTE) + 1 + CountLeadingZeroes32(DivisorParts.u.LowPart) - CountLeadingZeroes32(DividendParts.u.HighPart); /* Check if shift is 32-bit */ if(Shift == (sizeof(ULONG) * BITS_PER_BYTE)) { /* Get the quotient and remainder */ QuotientParts.u.LowPart = 0; QuotientParts.u.HighPart = DividendParts.u.LowPart; RemainderParts.u.LowPart = DividendParts.u.HighPart; RemainderParts.u.HighPart = 0; } else if(Shift < (sizeof(ULONG) * BITS_PER_BYTE)) { /* Shift is smaller, get the quotient and remainder */ QuotientParts.u.LowPart = 0; QuotientParts.u.HighPart = DividendParts.u.LowPart << ((sizeof(ULONG) * BITS_PER_BYTE) - Shift); RemainderParts.u.LowPart = (DividendParts.u.HighPart << ((sizeof(ULONG) * BITS_PER_BYTE) - Shift)) | (DividendParts.u.LowPart >> Shift); RemainderParts.u.HighPart = DividendParts.u.HighPart >> Shift; } else { /* Shift is larger, get the quotient and remainder */ QuotientParts.u.LowPart = DividendParts.u.LowPart << ((sizeof(ULONGLONG) * BITS_PER_BYTE) - Shift); QuotientParts.u.HighPart = (DividendParts.u.HighPart << ((sizeof(ULONGLONG) * BITS_PER_BYTE) - Shift)) | (DividendParts.u.LowPart >> (Shift - (sizeof(ULONG) * BITS_PER_BYTE))); RemainderParts.u.LowPart = DividendParts.u.HighPart >> (Shift - (sizeof(ULONG) * BITS_PER_BYTE)); RemainderParts.u.HighPart = 0; } } } else { /* Divisor is 64-bit value, check if dividend has low part set */ if(DividendParts.u.LowPart == 0) { /* Check if remainder provided */ if(Remainder != NULLPTR) { /* Calculate the remainder */ RemainderParts.u.HighPart = DividendParts.u.HighPart % DivisorParts.u.HighPart; RemainderParts.u.LowPart = 0; *Remainder = RemainderParts.QuadPart; } /* Return the quotient */ return DividendParts.u.HighPart / DivisorParts.u.HighPart; } /* Calculate the shift count */ Shift = CountLeadingZeroes32(DivisorParts.u.HighPart) - CountLeadingZeroes32(DividendParts.u.HighPart); /* Check if shift exceeds 32-bits */ if(Shift > ((sizeof(ULONG) * BITS_PER_BYTE) - 2)) { /* Check if remainder provided */ if(Remainder != NULLPTR) { /* Calculate the remainder */ *Remainder = DividendParts.QuadPart; } /* Return 0 */ return 0; } /* Increase shift and clear quotient low part */ Shift++; QuotientParts.u.LowPart = 0; /* Get the quotient high part and remainder */ QuotientParts.u.HighPart = DividendParts.u.LowPart << ((sizeof(ULONG) * BITS_PER_BYTE) - Shift); RemainderParts.u.HighPart = DividendParts.u.HighPart >> Shift; RemainderParts.u.LowPart = (DividendParts.u.HighPart << ((sizeof(ULONG) * BITS_PER_BYTE) - Shift)) | (DividendParts.u.LowPart >> Shift); } /* Perform the division until shift is zero */ Carry = 0; while(Shift > 0) { /* Shift the remainder and the quotient */ RemainderParts.u.HighPart = (RemainderParts.u.HighPart << 1) | (RemainderParts.u.LowPart >> ((sizeof(ULONG) * BITS_PER_BYTE) - 1)); RemainderParts.u.LowPart = (RemainderParts.u.LowPart << 1) | (QuotientParts.u.HighPart >> ((sizeof(ULONG) * BITS_PER_BYTE) - 1)); QuotientParts.u.HighPart = (QuotientParts.u.HighPart << 1) | (QuotientParts.u.LowPart >> ((sizeof(ULONG) * BITS_PER_BYTE) - 1)); QuotientParts.u.LowPart = (QuotientParts.u.LowPart << 1) | Carry; /* Set the carry and subtract the divisor */ Difference = (LONGLONG)(DivisorParts.QuadPart - RemainderParts.QuadPart - 1) >> ((sizeof(ULONGLONG) * BITS_PER_BYTE) - 1); Carry = Difference & 0x1; RemainderParts.QuadPart -= DivisorParts.QuadPart & Difference; Shift -= 1; } /* Add the carry to the quotient */ QuotientParts.QuadPart = (QuotientParts.QuadPart << 1) | Carry; /* Check if remainder provided */ if(Remainder != NULLPTR) { /* Calculate the remainder */ *Remainder = RemainderParts.QuadPart; } /* Return the quotient */ return QuotientParts.QuadPart; } /** * Divides a signed large integer by a 32-bit divisor. * * @param Dividend * Supplies a large integer to be divided. * * @param Divisor * Supplies a 32-bit divisor. * * @param Remainder * Supplies a pointer that receives the divide remainder. * * @return This routine returns the quotient. * * @since XT 1.0 */ XTAPI LARGE_INTEGER RTL::Math::DivideLargeInteger(IN LARGE_INTEGER Dividend, IN ULONG Divisor, OUT PULONG Remainder) { LONGLONG DividendSign, UDividend; LARGE_INTEGER LargeInt; /* Remove the sign bit from dividend if present */ DividendSign = Dividend.QuadPart >> ((sizeof(LONGLONG) * BITS_PER_BYTE) - 1); UDividend = (Dividend.QuadPart ^ DividendSign) - DividendSign; /* Calculate the quotient */ LargeInt.QuadPart = (DivideUnsigned64(UDividend, Divisor, NULLPTR) ^ DividendSign) - DividendSign; /* Make sure a pointer to remainder provided */ if(Remainder) { /* Calculate remainder */ *Remainder = Dividend.QuadPart - (LargeInt.QuadPart * Divisor); } /* Return the quotient */ return LargeInt; } /** * Gets the base exponent of a given floating point value. * * @param Value * Supplies the floating point value to get the base exponent of. * * @param PowerOfTen * Supplies a pointer that receives the power of ten associated with the base exponent. * * @return This routine returns the base exponent value. * * @since XT 1.0 */ XTAPI LONG RTL::Math::GetBaseExponent(IN DOUBLE Value, OUT PDOUBLE PowerOfTen) { LONG BaseExponent, CurrentExponent, Exponent; ULONG ExponentShift, ExponentMask; LARGE_DOUBLE Parts; DOUBLE Power; /* Calculate the exponent mask and shift */ ExponentMask = DOUBLE_EXPONENT_MASK >> (sizeof(ULONG) * BITS_PER_BYTE); ExponentShift = DOUBLE_EXPONENT_SHIFT - (sizeof(ULONG) * BITS_PER_BYTE); /* Check if value is zero */ if(Value == 0.0) { /* Return the power of ten and the exponent */ *PowerOfTen = 1.0; return 0; } /* Get the parts of the value and calculate the exponent by multiplying by log10(2) */ Parts.DoublePart = Value; BaseExponent = ((Parts.u.HighPart & ExponentMask) >> ExponentShift) - DOUBLE_EXPONENT_BIAS; Exponent = (LONG)((DOUBLE)BaseExponent * 0.30102999566) + 1; /* Set the initial values and calculate the exponent */ CurrentExponent = 0; Power = 1.0; if(Exponent > 0) { /* Calculate the exponent */ while(CurrentExponent + 10 <= Exponent) { Power *= 0.0000000001; CurrentExponent += 10; } while(CurrentExponent + 1 <= Exponent) { Power *= 0.1; CurrentExponent += 1; } } else { /* Calculate the exponent */ while(CurrentExponent - 10 >= Exponent) { Power *= 10000000000; CurrentExponent -= 10; } while(CurrentExponent - 1 >= Exponent) { Power *= 10.0; CurrentExponent -= 1; } } /* Normalize input value */ Value *= Power; /* Remove all leading zeros, if any */ while((Value != 0.0) && ((LONG)Value == 0)) { Value *= 10.0; Exponent -= 1; Power *= 10.0; } /* Return the power of ten and the exponent */ *PowerOfTen = Power; return Exponent; } /** * Determines whether a floating-point number is infinite. * * @param Value * Supplies the floating-point value to test. * * @return This routine returns TRUE if the argument is infinite or a NaN, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN RTL::Math::InfiniteDouble(IN DOUBLE Value) { /* DOUBLE argument in IEEE 754 standard format */ union { PDOUBLE Double; struct { UINT MantissaLow:32; UINT MantissaHigh:20; UINT Exponent:11; UINT Sign:1; } *DoubleS; } Var; /* Convert input double value to IEEE 754 format */ Var.Double = &Value; /* Return TRUE if it is infinite, or FALSE otherwise */ return ((Var.DoubleS->Exponent & 0x7FF) == 0x7FF); } /** * Multiplies a signed large integer by a signed integer. * * @param Multiplicand * Supplies a large integer to be multiplied. * * @param Multiplier * Supplies an integer by which the large integer is multiplied. * * @return This routine returns the result of the multiplication. * * @since XT 1.0 */ XTAPI LARGE_INTEGER RTL::Math::MultiplyLargeInteger(IN LARGE_INTEGER Multiplicand, IN LONG Multiplier) { LARGE_INTEGER LargeInt; /* Perform multiplication and return the result */ LargeInt.QuadPart = (LONGLONG) Multiplicand.QuadPart * Multiplier; return LargeInt; } /** * Determines whether a floating-point number is a NaN ("Not a Number"). * * @param Value * Supplies the floating-point value to test. * * @return This routine returns TRUE if the argument is a NaN, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN RTL::Math::NanDouble(IN DOUBLE Value) { /* DOUBLE argument in IEEE 754 standard format */ union { PDOUBLE Double; struct { UINT MantissaLow:32; UINT MantissaHigh:20; UINT Exponent:11; UINT Sign:1; } *DoubleS; } Var; /* Convert input double value to IEEE 754 format */ Var.Double = &Value; /* Return TRUE if it is NaN, or FALSE otherwise */ return (Var.DoubleS->Exponent == 0x7FF && (Var.DoubleS->MantissaHigh != 0 || Var.DoubleS->MantissaLow != 0)); } ================================================ FILE: xtoskrnl/rtl/memory.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/memory.cc * DESCRIPTION: Memory related routines * DEVELOPERS: Rafal Kupiec */ #include /** * This routine compares the first bytes of the specified memory buffers. * * @param LeftBuffer * Supplies a pointer to the first block of memory to compare. * * @param RightBuffer * Supplies a pointer to the second block of memory to compare. * * @param Length * Specifies a number of bytes to compare. * * @return This routine returns a number of bytes that are equal in both memory blocks. * * @since NT 3.5 */ XTAPI SIZE_T RTL::Memory::CompareMemory(IN PCVOID LeftBuffer, IN PCVOID RightBuffer, IN SIZE_T Length) { SIZE_T Bytes = 0; /* Check if there is anything to compare */ if(Length) { /* Iterate through whole buffer length */ while(Bytes < Length) { /* Compare bytes from both bufers */ if(((CONST PBYTE)LeftBuffer)[Bytes] != ((CONST PBYTE)RightBuffer)[Bytes]) { /* Buffers are different */ break; } /* Increase number of common bytes */ Bytes++; } } /* Return number of equal characters */ return Bytes; } /** * This routine copies a block of memory. * * @param Destination * Supplies a pointer to the buffer where data will be copied to. * * @param Source * Supplies a pointer to the source buffer that will be copied. * * @param Length * Specifies the number of bytes to copy. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID RTL::Memory::CopyMemory(OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length) { PCHAR DestinationBytes = (PCHAR)Destination; PCCHAR SourceBytes = (PCHAR)Source; /* Forward buffer copy */ while(Length--) { *DestinationBytes++ = *SourceBytes++; } } /** * This routine copies a block of memory either forward of backward, depeding * if source and destination buffers overlap or not. * * @param Destination * Supplies a pointer to the buffer where data will be copied to. * * @param Source * Supplies a pointer to the source buffer that will be copied. * * @param Length * Specifies the number of bytes to copy. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID RTL::Memory::MoveMemory(OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length) { PCHAR DestinationBytes = (PCHAR)Destination; PCHAR SourceBytes = (PCHAR)Source; /* Make sure there is anything to copy */ if((!SourceBytes) && (!DestinationBytes)) { return; } /* Check if source and destination overlaps */ if((DestinationBytes > SourceBytes) && (SourceBytes + Length > DestinationBytes)) { /* Backward buffer copy */ while(Length) { DestinationBytes[Length - 1] = SourceBytes[Length - 1]; Length--; } } else { /* Forward buffer copy */ CopyMemory(Destination, Source, Length); } } /** * This routine compares the first bytes of the specified memory buffers. * * @param LeftBuffer * Supplies a pointer to the first block of memory to compare. * * @param RightBuffer * Supplies a pointer to the second block of memory to compare. * * @param Length * Specifies a number of bytes to compare. * * @return Returns TRUE if both buffers are equal up to the specified length, or FALSE otherwise. * * @since XT 1.0 */ XTAPI BOOLEAN RTL::Memory::SameMemory(IN PCVOID LeftBuffer, IN PCVOID RightBuffer, IN SIZE_T Length) { return (CompareMemory(LeftBuffer, RightBuffer, Length) == Length) ? TRUE : FALSE; } /** * This routine fills a section of memory with a specified byte. * * @param Destination * Supplies a pointer to the buffer to fill. * * @param Byte * Supplies a pattern to fill memory. * * @param Length * Specifies a number of bytes to store in memory. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID RTL::Memory::SetMemory(OUT PVOID Destination, IN UCHAR Byte, IN SIZE_T Length) { PCHAR DestinationBytes = (PCHAR)Destination; /* Fill the buffer with specified byte */ while(Length--) { *DestinationBytes++ = Byte; } } /** * This routine fills a section of memory with zeroes. * * @param Destination * Supplies a pointer to the buffer to fill. * * @param Length * Specifies a number of bytes to be filled with zeroes. * * @return This routine does not return any value. * * @since NT 3.5 */ XTAPI VOID RTL::Memory::ZeroMemory(OUT PVOID Destination, IN SIZE_T Length) { /* Fill the buffer with zeroes */ SetMemory(Destination, 0, Length); } ================================================ FILE: xtoskrnl/rtl/sha1.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/sha1.cc * DESCRIPTION: SHA1 computation support * DEVELOPERS: Rafal Kupiec */ #include /** * Computes the SHA-1 hash of a buffer in a single step. * * @param Buffer * Supplies a pointer to the buffer containing the data to be hashed. * * @param BufferSize * Specifies the size of the buffer in bytes. * * @param Digest * Supplies a pointer to the buffer that receives the 20-byte SHA-1 hash digest. * * @return This routine returns STATUS_SUCCESS if the hash was computed successfully, * or STATUS_INVALID_PARAMETER if an invalid parameter was supplied. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::SHA1::ComputeDigest(IN PCUCHAR Buffer, IN SIZE_T BufferSize, OUT PUCHAR Digest) { RTL_SHA1_CONTEXT Context; XTSTATUS Status; /* Validate input parameters */ if(!Digest || (!Buffer && BufferSize > 0)) { /* Invalid parameters, return error */ return STATUS_INVALID_PARAMETER; } /* Initialize SHA-1 context */ Status = InitializeContext(&Context); if(Status != STATUS_SUCCESS) { /* Failed to initialize SHA-1 context, return error */ return Status; } /* Hash data and compute SHA-1 digest */ HashData(&Context, Buffer, BufferSize); ComputeHash(&Context, Digest); /* Return success */ return STATUS_SUCCESS; } /** * Finalizes the SHA-1 hash computation and provides the digest. * * @param Context * Supplies a pointer to the SHA-1 context structure. * * @param Digest * Supplies a pointer to a buffer that receives the 20-byte SHA-1 hash digest. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID RTL::SHA1::ComputeHash(IN OUT PRTL_SHA1_CONTEXT Context, OUT PUCHAR Digest) { ULONG Index, PaddingLength; UCHAR Padding[64]; UCHAR Bits[8]; /* Zero padding and append 0x80 to it */ RTL::Memory::ZeroMemory(Padding, 64); Padding[0] = 0x80; /* Encode the total message length in bits as a Big Endian 64-bit integer */ *(PULONG)(Bits) = RTL::Endianness::SwapByte32(Context->Count[1]); *(PULONG)(Bits + 4) = RTL::Endianness::SwapByte32(Context->Count[0]); /* Calculate padding length needed to align the message to 56 bytes */ Index = (Context->Count[0] >> 3) & 0x3F; PaddingLength = (Index < 56) ? (56 - Index) : (120 - Index); /* Append the padding bytes to the message stream to satisfy the block boundary */ HashData(Context, Padding, PaddingLength); /* Append bits before final transformation */ HashData(Context, Bits, 8); /* Store hash to output in Big Endian format */ Digest[0] = (UCHAR)((Context->State[0] >> 24) & 0xFF); Digest[1] = (UCHAR)((Context->State[0] >> 16) & 0xFF); Digest[2] = (UCHAR)((Context->State[0] >> 8) & 0xFF); Digest[3] = (UCHAR)(Context->State[0] & 0xFF); Digest[4] = (UCHAR)((Context->State[1] >> 24) & 0xFF); Digest[5] = (UCHAR)((Context->State[1] >> 16) & 0xFF); Digest[6] = (UCHAR)((Context->State[1] >> 8) & 0xFF); Digest[7] = (UCHAR)(Context->State[1] & 0xFF); Digest[8] = (UCHAR)((Context->State[2] >> 24) & 0xFF); Digest[9] = (UCHAR)((Context->State[2] >> 16) & 0xFF); Digest[10] = (UCHAR)((Context->State[2] >> 8) & 0xFF); Digest[11] = (UCHAR)(Context->State[2] & 0xFF); Digest[12] = (UCHAR)((Context->State[3] >> 24) & 0xFF); Digest[13] = (UCHAR)((Context->State[3] >> 16) & 0xFF); Digest[14] = (UCHAR)((Context->State[3] >> 8) & 0xFF); Digest[15] = (UCHAR)(Context->State[3] & 0xFF); Digest[16] = (UCHAR)((Context->State[4] >> 24) & 0xFF); Digest[17] = (UCHAR)((Context->State[4] >> 16) & 0xFF); Digest[18] = (UCHAR)((Context->State[4] >> 8) & 0xFF); Digest[19] = (UCHAR)(Context->State[4] & 0xFF); /* Clear context memory for security */ RTL::Memory::ZeroMemory(Context, sizeof(RTL_SHA1_CONTEXT)); } /** * Updates the SHA-1 context with the provided data buffer. * * @param Context * Supplies a pointer to the SHA-1 context structure. * * @param Data * Supplies a pointer to the buffer containing the data to be hashed. * * @param Length * Specifies the length of the data buffer in bytes. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID RTL::SHA1::HashData(IN OUT PRTL_SHA1_CONTEXT Context, IN PCUCHAR Data, IN ULONG Length) { ULONG Index, Input, PartialLength; /* Calculate byte offset within the 64-byte block buffer */ Index = (Context->Count[0] >> 3) & 0x3F; /* Update the total bit count, handling overflow from low to high word */ if((Context->Count[0] += (Length << 3)) < (Length << 3)) { /* Increment high 32-bit counter on low counter overflow */ Context->Count[1]++; } /* Add the high-order bits of the length (bytes -> bits overflow) to the high counter */ Context->Count[1] += (Length >> 29); /* Calculate the number of bytes required to fill the remaining buffer space */ PartialLength = 64 - Index; /* Transform as many times as possible */ if(Length >= PartialLength) { /* Fill the buffer partially and transform */ RTL::Memory::CopyMemory(&Context->Buffer[Index], Data, PartialLength); TransformData(Context->State, Context->Buffer); /* Process remaining full 64-byte blocks directly from the input pointer */ for(Input = PartialLength; Input + 63 < Length; Input += 64) { /* Transform the full block without copying to the internal buffer */ TransformData(Context->State, &Data[Input]); } /* Reset buffer index to indicate the buffer is now empty */ Index = 0; } else { /* No full block was formed, begin copying from the start of input */ Input = 0; } /* Buffer remaining input */ RTL::Memory::CopyMemory(&Context->Buffer[Index], &Data[Input], Length - Input); } /** * Initializes a SHA-1 context structure with the standard initial hash values. * * @param Context * Supplies a pointer to the SHA-1 context structure to initialize. * * @return This routine returns STATUS_SUCCESS if the context was initialized successfully, * or STATUS_INVALID_PARAMETER if the pointer is NULLPTR. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::SHA1::InitializeContext(OUT PRTL_SHA1_CONTEXT Context) { /* Validate input parameter */ if(!Context) { /* Invalid parameter, return error */ return STATUS_INVALID_PARAMETER; } /* Initialize hash constants defined by FIPS 180-4 */ Context->State[0] = 0x67452301; Context->State[1] = 0xEFCDAB89; Context->State[2] = 0x98BADCFE; Context->State[3] = 0x10325476; Context->State[4] = 0xC3D2E1F0; Context->Count[0] = 0; Context->Count[1] = 0; /* Clear buffer */ RTL::Memory::ZeroMemory(Context->Buffer, SHA1_BLOCK_SIZE); /* Return success */ return STATUS_SUCCESS; } /** * Transforms a single 64-byte block using the SHA-1 compression function. * * @param State * Supplies a pointer to the array containing the current hash state variables. * * @param Buffer * Supplies a pointer to the 64-byte input buffer to be transformed. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID RTL::SHA1::TransformData(IN OUT PULONG State, IN PCUCHAR Buffer) { ULONG Constant, Function, Index, TempHash; ULONG TempState[5]; ULONG Stack[80]; /* Initialize working variables with current state */ TempState[0] = State[0]; TempState[1] = State[1]; TempState[2] = State[2]; TempState[3] = State[3]; TempState[4] = State[4]; /* Initialize the first 16 words of the message schedule from the input buffer */ for(Index = 0; Index < 16; Index++) { /* Convert input words from Little Endian to Big Endian required by SHA-1 */ Stack[Index] = RTL::Endianness::SwapByte32(((const PULONG)Buffer)[Index]); } /* Expand the message to 80 words using the SHA-1 algorithm */ for(Index = 16; Index < 80; Index++) { /* Compute the next word value based on XOR and left rotation */ Stack[Index] = ROTATE_LEFT((Stack[Index - 3] ^ Stack[Index - 8] ^ Stack[Index - 14] ^ Stack[Index - 16]), 1); } /* Execute the main compression loop for 80 rounds */ for(Index = 0; Index < 80; Index++) { /* Determine the logical function and constant based on the current round */ if(Index < 20) { /* Set the constant defined by FIPS 180-4 for rounds 0-19 and calculate the logical function */ Constant = 0x5A827999; Function = (TempState[1] & TempState[2]) | ((~TempState[1]) & TempState[3]); } else if(Index < 40) { /* Set the constant defined by FIPS 180-4 for rounds 20-39 and calculate the logical function */ Constant = 0x6ED9EBA1; Function = TempState[1] ^ TempState[2] ^ TempState[3]; } else if(Index < 60) { /* Set the constant defined by FIPS 180-4 for rounds 40-59 and calculate the logical function */ Constant = 0x8F1BBCDC; Function = (TempState[1] & TempState[2]) | (TempState[1] & TempState[3]) | (TempState[2] & TempState[3]); } else { /* Set the constant defined by FIPS 180-4 for rounds 60-79 and calculate the logical function */ Constant = 0xCA62C1D6; Function = TempState[1] ^ TempState[2] ^ TempState[3]; } /* Calculate the temporary hash value for this round */ TempHash = ROTATE_LEFT(TempState[0], 5) + Function + TempState[4] + Constant + Stack[Index]; TempState[4] = TempState[3]; TempState[3] = TempState[2]; TempState[2] = ROTATE_LEFT(TempState[1], 30); TempState[1] = TempState[0]; TempState[0] = TempHash; } /* Add the compressed chunk to the current hash value */ State[0] += TempState[0]; State[1] += TempState[1]; State[2] += TempState[2]; State[3] += TempState[3]; State[4] += TempState[4]; /* Clear sensitive data from stack */ RTL::Memory::ZeroMemory(Stack, sizeof(Stack)); } ================================================ FILE: xtoskrnl/rtl/slist.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/slist.cc * DESCRIPTION: Singly linked list manipulation routines * DEVELOPERS: Rafal Kupiec */ #include /** * Retrieves the first entry from a singly linked list without removing it from the list. * * @param ListHead * Supplies a pointer to a structure that serves as the list header. * * @return This routine returns a pointer to the first entry in the list, or NULLPTR if the list is empty. * * @since XT 1.0 */ XTCDECL PSINGLE_LIST_ENTRY RTL::SinglyList::GetFirstEntry(IN PSINGLE_LIST_HEADER ListHead) { /* Check if the list is empty */ if(ListEmpty(ListHead)) { /* Empty list, return NULLPTR */ return NULLPTR; } /* Return first entry in the list */ return ListHead->Next.Next; } /** * Initializes a structure representing the head of a singly linked list. * * @param ListHead * Supplies a pointer to a structure that serves as the list header. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::SinglyList::InitializeListHead(IN PSINGLE_LIST_HEADER ListHead) { /* Initialize the singly linked list head */ ListHead->Alignment = 0; } /** * Inserts an entry at the head of a singly linked list. * * @param ListHead * Supplies a pointer to the head of the list. * * @param Entry * Supplies a pointer to the entry that will be inserted in the list. * * @return This routine returns a pointer to the original first entry in the list. * * @since XT 1.0 */ XTCDECL PSINGLE_LIST_ENTRY RTL::SinglyList::InsertHeadList(IN OUT PSINGLE_LIST_HEADER ListHead, IN PSINGLE_LIST_ENTRY Entry) { PSINGLE_LIST_ENTRY OriginalEntry; /* Store the original first entry */ OriginalEntry = ListHead->Next.Next; /* Insert entry at the head of the list and increment depth and sequence */ Entry->Next = ListHead->Next.Next; ListHead->Next.Next = Entry; ListHead->Depth++; ListHead->Sequence++; /* Return original first entry */ return OriginalEntry; } /** * Inserts an entry at the tail of a singly linked list. * * @param ListHead * Supplies a pointer to the head of the list. * * @param Entry * Supplies a pointer to the entry that will be inserted in the list. * * @return This routine returns a pointer to the original last entry in the list. * * @since XT 1.0 */ XTCDECL PSINGLE_LIST_ENTRY RTL::SinglyList::InsertTailList(IN OUT PSINGLE_LIST_HEADER ListHead, IN PSINGLE_LIST_ENTRY Entry) { PSINGLE_LIST_ENTRY CurrentEntry, OriginalEntry; /* Set Next pointer of the new entry to NULLPTR */ Entry->Next = NULLPTR; /* Check if the list is empty */ if(ListEmpty(ListHead)) { /* Store the original last entry */ OriginalEntry = ListHead->Next.Next; /* Insert entry at the head */ ListHead->Next.Next = Entry; } else { /* Traverse the list to find the last entry */ CurrentEntry = ListHead->Next.Next; while(CurrentEntry->Next != NULLPTR) { /* Move to the next entry */ CurrentEntry = CurrentEntry->Next; } /* Store the original last entry */ OriginalEntry = CurrentEntry; /* Insert entry at the tail */ CurrentEntry->Next = Entry; } /* Increment list depth and sequence */ ListHead->Depth++; ListHead->Sequence++; /* Return original last entry */ return OriginalEntry; } /** * Indicates whether a singly linked list structure is empty, or not initialized at all. * * @param ListHead * Supplies a pointer to a structure that represents the head of the list. * * @return This routine returns TRUE if there are currently no entries in the list or FALSE otherwise. * * @since XT 1.0 */ XTCDECL BOOLEAN RTL::SinglyList::ListEmpty(IN PSINGLE_LIST_HEADER ListHead) { /* Check if the list is empty */ return (ListHead == NULLPTR || ListHead->Next.Next == NULLPTR); } /** * Queries the current depth (number of entries) of a singly linked list. * * @param ListHead * Supplies a pointer to a structure that represents the head of the singly linked list. * * @return This routine returns the number of entries currently in the list, or zero if the list head is NULLPTR. * * @since XT 1.0 */ XTAPI USHORT RTL::SinglyList::QueryListDepth(IN PSINGLE_LIST_HEADER ListHead) { /* Check if the list head is initialized and valid */ if(ListHead == NULLPTR) { /* Return zero */ return 0; } /* Return the list depth */ return ListHead->Depth; } /** * Removes an entry from a singly linked list. * * @param ListHead * Supplies a pointer to the head of the list. * * @param Entry * Supplies a pointer to the entry that will be removed from the list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::SinglyList::RemoveEntryList(IN PSINGLE_LIST_HEADER ListHead, IN PSINGLE_LIST_ENTRY Entry) { PSINGLE_LIST_ENTRY PreviousEntry; /* Check if the list is empty */ if(ListEmpty(ListHead)) { /* List is empty, nothing to remove, return */ return; } /* Check if the entry is the first one */ if(ListHead->Next.Next == Entry) { /* Remove the first entry and decrement depth */ ListHead->Next.Next = Entry->Next; ListHead->Depth--; /* Nothing else to do, return */ return; } /* Find the previous entry */ PreviousEntry = ListHead->Next.Next; while(PreviousEntry->Next != Entry) { /* Move to the next entry */ PreviousEntry = PreviousEntry->Next; /* Check if we reached the end of the list */ if(PreviousEntry == NULLPTR) { /* Entry not found, return */ return; } } /* Remove the entry and decrement depth */ PreviousEntry->Next = Entry->Next; ListHead->Depth--; } /** * Splices a singly linked list at the head of another list. The source list is reinitialized to empty. * * @param ListHead * Supplies a pointer to a structure that represents the head of the list. * * @param SpliceList * Supplies a pointer to a structure that represents the head of the list that will be spliced. * * @return This routine returns a pointer to the original first entry in the list. * * @since XT 1.0 */ XTCDECL PSINGLE_LIST_ENTRY RTL::SinglyList::SpliceHeadList(IN OUT PSINGLE_LIST_HEADER ListHead, IN OUT PSINGLE_LIST_HEADER SpliceList) { PSINGLE_LIST_ENTRY LastEntry, OriginalEntry; /* Store the original last entry */ OriginalEntry = ListHead->Next.Next; /* Check if the list to splice is empty */ if(ListEmpty(SpliceList)) { /* Nothing to splice, return original first entry */ return OriginalEntry; } /* Find the last entry of the list to splice */ LastEntry = SpliceList->Next.Next; while(LastEntry->Next != NULLPTR) { /* Move to the next entry */ LastEntry = LastEntry->Next; } /* Splice the list at the head of destination */ LastEntry->Next = ListHead->Next.Next; ListHead->Next.Next = SpliceList->Next.Next; /* Update depth and sequence of the destination list */ ListHead->Depth += SpliceList->Depth; ListHead->Sequence++; /* Reinitialize the source list to empty */ SpliceList->Next.Next = NULLPTR; SpliceList->Depth = 0; /* Return the original last entry */ return OriginalEntry; } /** * Splices a singly linked list at the tail of another list. The source list is reinitialized to empty. * * @param ListHead * Supplies a pointer to the head of the destination list. * * @param SpliceList * Supplies a pointer to the head of the list that will be spliced. * * @return This routine returns a pointer to the original last entry in the list. * * @since XT 1.0 */ XTCDECL PSINGLE_LIST_ENTRY RTL::SinglyList::SpliceTailList(IN OUT PSINGLE_LIST_HEADER ListHead, IN OUT PSINGLE_LIST_HEADER SpliceList) { PSINGLE_LIST_ENTRY LastEntry, OriginalEntry; /* Check if the destination list is empty */ if(ListEmpty(ListHead)) { /* Destination is empty, original last entry is NULLPTR */ OriginalEntry = NULLPTR; /* Move the splice list to the destination head */ ListHead->Next.Next = SpliceList->Next.Next; } else { /* Find the last entry of the destination list */ LastEntry = ListHead->Next.Next; while(LastEntry->Next != NULLPTR) { /* Move to the next entry */ LastEntry = LastEntry->Next; } /* Store the original last entry */ OriginalEntry = LastEntry; /* Splice the list at the tail of destination */ LastEntry->Next = SpliceList->Next.Next; } /* Update depth and sequence of the destination list */ ListHead->Depth += SpliceList->Depth; ListHead->Sequence++; /* Reinitialize the source list to empty */ SpliceList->Next.Next = NULLPTR; SpliceList->Depth = 0; /* Return the original last entry */ return OriginalEntry; } /** * Retrieves the first entry from a singly linked list and removes it from the list. * * @param ListHead * Pointer to a structure that serves as the list header. * * @return This routine returns a pointer to the first entry in the list, or NULLPTR if the list is empty. * * @since XT 1.0 */ XTCDECL PSINGLE_LIST_ENTRY RTL::SinglyList::TakeFirstEntry(IN PSINGLE_LIST_HEADER ListHead) { PSINGLE_LIST_ENTRY Entry; /* Check if the list is empty */ if(ListEmpty(ListHead)) { /* List is empty, return NULLPTR */ return NULLPTR; } /* Get the first entry */ Entry = ListHead->Next.Next; /* Remove entry from the list */ ListHead->Next.Next = Entry->Next; ListHead->Depth--; /* Return the first entry */ return Entry; } ================================================ FILE: xtoskrnl/rtl/string.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/string.cc * DESCRIPTION: String support * DEVELOPERS: Rafal Kupiec */ #include /** * Compares at most specified number of characters of two C strings. * * @param String1 * String to be compared. * * @param String2 * String to be compared. * * @param Length * Maximum number of characters to compare. If no limit set, it compares whole strings. * * @return Integral value indicating the relationship between the strings. * * @since XT 1.0 */ XTAPI SIZE_T RTL::String::CompareString(IN PCSTR String1, IN PCSTR String2, IN SIZE_T Length) { SIZE_T Index; /* Iterate through the strings */ for(Index = 0; ; Index++) { /* Check if length limit reached */ if(Index != 0 && Index == Length) { /* Skip checking next characters */ break; } /* Check if string characters are equal */ if(String1[Index] != String2[Index]) { /* Different characters found */ return String1[Index] < String2[Index] ? -1 : 1; } /* Check if end of string reached */ if(!String1[Index] || !String2[Index]) { /* Equal strings until the end of one of them */ return 0; } } /* Strings are equal */ return 0; } /** * Compares at most specified number of characters of two C strings, while ignoring differences in case. * * @param String1 * String to be compared. * * @param String2 * String to be compared. * * @param Length * Maximum number of characters to compare. If no limit set, it compares whole strings. * * @return Integral value indicating the relationship between the strings. * * @since XT 1.0 */ XTAPI SIZE_T RTL::String::CompareStringInsensitive(IN PCSTR String1, IN PCSTR String2, IN SIZE_T Length) { CHAR Character1; CHAR Character2; ULONG Index = 0; /* Iterate through the strings */ while(String1[Index] != '\0' && String2[Index] != '\0') { /* Check if length limit reached */ if(Index != 0 && Index == Length) { /* Skip checking next characters */ break; } /* Get the characters */ Character1 = String1[Index]; Character2 = String2[Index]; /* Lowercase string1 character if needed */ if(String1[Index] >= 'A' && String1[Index] <= 'Z') { Character1 = String1[Index] - 'A' + 'a'; } /* Lowercase string2 character if needed */ if(String2[Index] >= 'A' && String2[Index] <= 'Z') { Character2 = String2[Index] - 'A' + 'a'; } /* Compare the characters */ if(Character1 != Character2) { /* Strings are not equal */ return Character1 > Character2 ? 1 : -1; } /* Get next character */ Index++; } /* Strings are equal */ return 0; } /** * Appends a copy of the source string to the end of the destination string. * * @param Destination * Supplies a pointer to the NULL-terminated string to append to. * * @param Source * Supplies a pointer to the NULL-terminated string to copy from. * * @param Count * Sets a maximum number of characters to copy. If no limit set, appends whole string. * * @return This routine returns a copy of a destination string. * * @since XT 1.0 */ XTAPI PCHAR RTL::String::ConcatenateString(OUT PCHAR Destination, IN PCHAR Source, IN SIZE_T Count) { PCHAR DestString = Destination; /* Go to the end of destination string */ while(*Destination) { Destination++; } /* Check if copy limit set */ if(Count > 0) { /* Copy character-by-character */ do { /* Check if NULL-terminated character found */ if((*Destination = *Source++) == '\0') { /* Break on '\0' character */ break; } Destination++; } while(--Count != 0); /* Add NULL-termination character to the end of destination string */ *Destination = '\0'; } else { /* No limit set, copy all characters */ while((*Destination++ = *Source++) != 0); } /* Return copy of the destination string */ return DestString; } /** * Copies a string from a buffer into another buffer, ensuring that the destination string is NULL-terminated. * * @param Destination * Supplies a pointer to the destination buffer. * * @param Source * Supplies a pointer to the source buffer. * * @param Length * Supplies the length of the string to copy. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID RTL::String::CopyString(IN PCHAR Destination, IN PCSTR Source, IN ULONG Length) { ULONG Index; /* Copy characters */ for(Index = 0; Index < Length; Index++) { /* Copy source character */ Destination[Index] = Source[Index]; /* Check if NULL-terminated character found */ if(Source[Index] == '\0') { /* End of source string reached */ break; } } /* Make sure the destination string is terminated properly */ Destination[Index] = '\0'; } /** * Finds the first occurrence of the search string in the source string. * * @param Source * Supplies a pointer to the source string. * * @param Search * Supplies a pointer to the search string. * * @return This routine returns a pointer to the first occurrence of the search string in the source string. * * @since XT 1.0 */ XTAPI PCSTR RTL::String::FindString(IN PCSTR Source, IN PCSTR Search) { PCSTR CurrentSource; PCSTR CurrentSearch; /* Validate input parameters */ if(!Source || !Search) { /* Invalid input parameters, return NULLPTR */ return NULLPTR; } /* Check if search string is empty */ if(*Search == '\0') { /* Return the source string */ return Source; } /* Iterate through the source string */ for(; *Source != '\0'; Source++) { /* Initialize pointers */ CurrentSource = Source; CurrentSearch = Search; /* Check if the substring matches starting at the current position */ while(*CurrentSource != '\0' && *CurrentSearch != '\0' && *CurrentSource == *CurrentSearch) { /* Go to the next character */ CurrentSource++; CurrentSearch++; } /* If we reached the end of Search string, it is a match */ if(*CurrentSearch == '\0') { /* Return the source position */ return Source; } } /* No match found, return NULLPTR */ return NULLPTR; } /** * Finds the first case-insensitive occurrence of the search string in the source string. * * @param Source * Supplies a pointer to the source string. * * @param Search * Supplies a pointer to the search string. * * @return This routine returns a pointer to the first occurrence of the search string in the source string. * * @since XT 1.0 */ XTAPI PCSTR RTL::String::FindStringInsensitive(IN PCSTR Source, IN PCSTR Search) { PCSTR CurrentSource; PCSTR CurrentSearch; /* Validate input parameters */ if(!Source || !Search) { /* Invalid input parameters, return NULLPTR */ return NULLPTR; } /* Check if search string is empty */ if(*Search == '\0') { /* Return the source string */ return Source; } /* Iterate through the source string */ for(; *Source != '\0'; Source++) { /* Initialize pointers */ CurrentSource = Source; CurrentSearch = Search; /* Check if the substring matches starting at the current position */ while(*CurrentSource != '\0' && *CurrentSearch != '\0' && ToLowerCharacter(*CurrentSource) == ToLowerCharacter(*CurrentSearch)) { /* Go to the next character */ CurrentSource++; CurrentSearch++; } /* If we reached the end of Search string, it is a match */ if(*CurrentSearch == '\0') { /* Return the source position */ return Source; } } /* No match found, return NULLPTR */ return NULLPTR; } /** * Reverses a characters order in a string. It modifies the original, input variable. * * @param String * Supplies a pointer to the string to reverse. * * @param Length * Supplies the length of the string to reverse. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID RTL::String::ReverseString(IN OUT PCHAR String, IN ULONG Length) { UCHAR TempChar; ULONG Index; /* Iterate through the string */ for(Index = 0; Index < (Length / 2); Index++) { /* Swap characters */ TempChar = String[Index]; String[Index] = String[Length - Index - 1]; String[Length - Index - 1] = TempChar; } } /** * Calculates the length of a given string. * * @param String * Pointer to the NULL-terminated string to be examined. * * @param MaxLength * Maximum number of characters to examine. If no limit set, it examines whole string. * * @return The length of the NULL-terminated string. * * @since: XT 1.0 */ XTAPI SIZE_T RTL::String::StringLength(IN PCSTR String, IN SIZE_T MaxLength) { SIZE_T Length; /* Check if NULL pointer passed */ if(String == NULLPTR) { return 0; } /* Iterate through the wide string */ for(Length = 0; ; Length++) { /* Check if NULL found or max length limit reached */ if((Length != 0 && Length == MaxLength) || !String[Length]) { /* Finish examination */ break; } } /* Return string length */ return Length; } /** * Converts a string to a number. * * @param String * Supplies a pointer to the NULL-terminated string to convert. * * @param Base * Supplies the optional numerical base for the conversion (2, 8, 10, or 16). * * @param Value * Supplies a pointer to a variable that receives the converted numeric value. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::String::StringToNumber(IN PCSTR String, IN ULONG Base, OUT PULONG Value) { BOOLEAN NegativeValue; ULONG Digit, Result; /* Validate input parameters */ if(!String || !Value) { /* Invalid input parameters, return error code */ return STATUS_INVALID_PARAMETER; } /* Initialize local variables */ NegativeValue = FALSE; Result = 0; /* Skip leading whitespaces and control characters */ while(*String != '\0' && *String <= ' ') { /* Advance to the next character */ String++; } /* Consume and record sign */ if(*String == '-') { /* Set negative value flag and advance to the next character */ NegativeValue = TRUE; String++; } else if(*String == '+') { /* Advance to the next character */ String++; } /* Autodetect and validate the base */ if(Base == 0) { /* Autodetect base based on prefix */ if(String[0] == '0') { /* Validate prefix */ if(String[1] == 'x' || String[1] == 'X') { /* Hexadecimal base */ Base = 16; String += 2; } else if(String[1] == 'o' || String[1] == 'O') { /* Octal base */ Base = 8; String += 2; } else if(String[1] == 'b' || String[1] == 'B') { /* Binary base */ Base = 2; String += 2; } else { /* Starts with 0 but no known prefix, treat as decimal */ Base = 10; } } else { /* Default to decimal base */ Base = 10; } } else { /* Validate explicitly provided base */ if(Base != 2 && Base != 8 && Base != 10 && Base != 16) { /* Invalid base, return error code */ return STATUS_INVALID_PARAMETER; } /* Check if number starts with 0 */ if(String[0] == '0') { /* Check for prefix */ if(Base == 16 && (String[1] == 'x' || String[1] == 'X')) { /* Skip hexadecimal prefix */ String += 2; } else if(Base == 8 && (String[1] == 'o' || String[1] == 'O')) { /* Skip octal prefix */ String += 2; } else if(Base == 2 && (String[1] == 'b' || String[1] == 'B')) { /* Skip binary prefix */ String += 2; } } } /* Parse string character by character */ while(*String != '\0') { /* Convert character to numeric digit */ if(*String >= '0' && *String <= '9') { /* Convert decimal digit */ Digit = *String - '0'; } else if(*String >= 'A' && *String <= 'F') { /* Convert hexadecimal digit */ Digit = *String - 'A' + 10; } else if(*String >= 'a' && *String <= 'f') { /* Convert hexadecimal digit */ Digit = *String - 'a' + 10; } else { /* Invalid character for a number encountered, stop parsing */ break; } /* Check if digit is valid for the current base */ if(Digit >= Base) { /* Digit out of range for this base, stop parsing */ break; } /* Check for integer overflow */ if((Result > (MAXULONG / Base)) || ((Result * Base) > (MAXULONG - Digit))) { /* Integer overflow, return error code */ return STATUS_INTEGER_OVERFLOW; } /* Accumulate result */ Result = (Result * Base) + Digit; /* Advance to the next character */ String++; } /* Check for negative value */ if(NegativeValue) { /* Apply sign and return the result */ *Value = (ULONG)(-(LONG)Result); } else { /* Return the result */ *Value = Result; } /* Return success */ return STATUS_SUCCESS; } /** * Converts a multibyte character string to its wide character representation. * * @param Destination * Pointer to wide character array where the wide string will be stored * * @param Source * Pointer to the first element of a multibyte string to convert. * * @param Length * Number of characters in the source string. * * @return Returns the number of wide characters written to the destination array on success, or -1 on error. * * @since XT 1.0 */ XTAPI SIZE_T RTL::String::StringToWideString(OUT PWCHAR Destination, IN PCSTR *Source, IN SIZE_T Length) { PCSTR LocalSource = *Source; SIZE_T Count = Length; /* Check if NULL pointer passed */ if(Destination == NULLPTR) { /* No wide characters written */ return 0; } /* Iterate through the string */ while(Count) { /* Copy character */ if((*Destination = *LocalSource) == 0) { /* End of string reached */ LocalSource = NULLPTR; break; } /* Check if character is valid */ if(*Destination >= 0x80) { /* Invalid character, return error */ return -1; } /* Advance pointers */ LocalSource++; Destination++; Count--; } /* Return number of wide characters written */ return Length - Count; } /** * Finds the next token in a NULL-terminated string. * * @param String * Pointer to the NULL-terminated string to tokenize. * * @param Delimiter * Pointer to the NULL-terminated string identifying delimiters. * * @param SavePtr * Pointer to an object used to store routine internal state. * * @return Pointer to the beginning of the next token or NULL if there are no more tokens. * * @since: XT 1.0 */ XTAPI PCHAR RTL::String::TokenizeString(IN PCHAR String, IN PCSTR Delimiter, IN OUT PCHAR *SavePtr) { PCHAR Span, Token; CHAR Char, SpanChar; /* Check if there is anything to tokenize */ if(String == NULLPTR && (String = *SavePtr) == NULLPTR) { /* Empty string given */ return NULLPTR; } /* Check non-delimiter characters */ Char = *String++; if(Char == '\0') { *SavePtr = NULLPTR; return NULLPTR; } Token = String - 1; /* Scan token for delimiters */ for(;;) { Char = *String++; Span = (PCHAR)Delimiter; do { /* Check if delimiter found */ if((SpanChar = *Span++) == Char) { /* Check if end of string reached */ if(Char == '\0') { /* End of string reached, no more tokens */ String = NULLPTR; } else { /* Terminate token */ String[-1] = '\0'; } /* Store pointer to the next token */ *SavePtr = String; /* Return token */ return Token; } } while(SpanChar != '\0'); } } /** * Converts a character to lowercase. * * @param Character * Character to be converted. * * @return Converted character or original character if it was not uppercase. * * @since XT 1.0 */ XTAPI CHAR RTL::String::ToLowerCharacter(IN CHAR Character) { /* Check if character is uppercase */ if(Character >= 'A' && Character <= 'Z') { /* Convert character to lowercase */ return (CHAR)(Character + ('a' - 'A')); } /* Return original character */ return Character; } /** * Converts a character to uppercase. * * @param Character * Character to be converted. * * @return Converted character or original character if it was not lowercase. * * @since XT 1.0 */ XTAPI CHAR RTL::String::ToUpperCharacter(IN CHAR Character) { /* Check if character is lowercase */ if(Character >= 'a' && Character <= 'z') { /* Convert character to uppercase */ return (CHAR)(Character - ('a' - 'A')); } /* Return original character */ return Character; } /** * Removes certain characters from a beginning of the string. * * @param String * Pointer to the NULL-terminated string to be trimmed. * * @return This routine returns a pointer to the left-trimmed string. * * @since XT 1.0 */ XTAPI PCHAR RTL::String::TrimLeftString(IN PCHAR String) { PCHAR Start; /* Initialize pointer */ Start = String; /* Skip all leading whitespaces */ while(*Start == ' ' || *Start == '\n' || *Start == '\t' || *Start == '\r' || *Start == '\v' || *Start == '\f') { /* Advance to the next character */ Start++; } /* Return left-trimmed string */ return Start; } /** * Removes certain characters from the end of the string. * * @param String * Pointer to the NULL-terminated string to be trimmed. * * @return This routine returns a pointer to the right-trimmed string. * * @since XT 1.0 */ XTAPI PCHAR RTL::String::TrimRightString(IN PCHAR String) { PCHAR End; /* Find end of the string */ End = String + StringLength(String, 0); /* Skip all trailing whitespaces */ while((End != String) && (*End == ' ' || *End == '\n' || *End == '\t' || *End == '\r' || *End == '\v' || *End == '\f')) { /* Move to the previous character */ End--; } /* Terminate the string */ *End = 0; /* Return right-trimmed string */ return String; } /** * Removes certain characters from the beginning and the end of the string. * * @param String * Pointer to the NULL-terminated string to be trimmed. * * @return This routine returns a pointer to the trimmed string. * * @since XT 1.0 */ XTAPI PCHAR RTL::String::TrimString(IN PCHAR String) { return TrimLeftString(TrimRightString(String)); } ================================================ FILE: xtoskrnl/rtl/time.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/time.cc * DESCRIPTION: Time conversion support * DEVELOPERS: Aiken Harris */ #include /** * Determines if a given year is a leap year in the Gregorian calendar. * * @param Year * Supplies the year to be checked. * * @return This routine returns TRUE if the year is a leap year, FALSE otherwise. * * @since XT 1.0 */ XTFASTCALL BOOLEAN RTL::Time::LeapYear(SHORT Year) { return ((Year % 4 == 0 && Year % 100 != 0) || (Year % 400 == 0)) ? TRUE : FALSE; } /** * Converts a TIME_FIELDS calendar structure to a 64-bit Unix timestamp. * * @param TimeFields * Supplies a pointer to a fully populated TIME_FIELDS structure. * * @param UnixTime * Supplies a pointer to a 64-bit integer that receives the number of * seconds elapsed since January 1, 1970. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::Time::TimeFieldsToUnixEpoch(IN PTIME_FIELDS TimeFields, OUT PLONGLONG UnixTime) { LONGLONG ElapsedDays, TotalSeconds; LONG Month, Year; ULONG Leap; /* Check leap year */ Leap = LeapYear(TimeFields->Year) ? 1 : 0; /* 2. Validate input data */ if(TimeFields->Hour < 0 || TimeFields->Hour > 23 || TimeFields->Minute < 0 || TimeFields->Minute > 59 || TimeFields->Second < 0 || TimeFields->Second > 59 || TimeFields->Year < 0 || TimeFields->Year > 30827 || TimeFields->Month < 1 || TimeFields->Month > 12 || TimeFields->Day < 1 || TimeFields->Day > DaysInMonth[Leap][TimeFields->Month - 1]) { /* Invalid input data, return error code */ return STATUS_INVALID_PARAMETER; } /* Copy year and month */ Year = (LONG)TimeFields->Year; Month = (LONG)TimeFields->Month; /* Put February at the end of the calculation cycle, making leap day handling implicit in the year division */ if(0 >= (LONG)(Month -= 2)) { /* Adjust month and year */ Month += 12; Year -= 1; } /* Calculate absolute elapsed days */ ElapsedDays = (LONGLONG)(Year/4 - Year/100 + Year/400 + 367*Month/12 + TimeFields->Day) + (LONGLONG)Year*365 - 719499LL; /* Calculate total seconds */ TotalSeconds = (ElapsedDays * TIME_SECONDS_PER_DAY) + ((LONGLONG)TimeFields->Hour * TIME_SECONDS_PER_HOUR) + ((LONGLONG)TimeFields->Minute * TIME_SECONDS_PER_MINUTE) + (LONGLONG)TimeFields->Second; /* Output the final Unix timestamp */ *UnixTime = TotalSeconds; /* Return success */ return STATUS_SUCCESS; } /** * Converts a TIME_FIELDS calendar structure to a 64-bit XT timestamp. * * @param TimeFields * Supplies a pointer to a fully populated TIME_FIELDS structure. * * @param Time * Supplies a pointer to variable that receives the converted time value in 100-nanosecond * intervals since January 1, 1601. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::Time::TimeFieldsToXtEpoch(IN PTIME_FIELDS TimeFields, OUT PLARGE_INTEGER XtTime) { LONGLONG ElapsedDays, TotalSeconds; LONG Month, Year; ULONG Leap; /* Check leap year */ Leap = LeapYear(TimeFields->Year) ? 1 : 0; /* Validate input data */ if(TimeFields->Hour < 0 || TimeFields->Hour > 23 || TimeFields->Minute < 0 || TimeFields->Minute > 59 || TimeFields->Second < 0 || TimeFields->Second > 59 || TimeFields->Milliseconds < 0 || TimeFields->Milliseconds > 999 || TimeFields->Year < 1601 || TimeFields->Year > 30827 || TimeFields->Month < 1 || TimeFields->Month > 12 || TimeFields->Day < 1 || TimeFields->Day > DaysInMonth[Leap][TimeFields->Month - 1]) { /* Invalid input data, return error code */ return STATUS_INVALID_PARAMETER; } /* Copy year and month */ Year = (LONG)TimeFields->Year; Month = (LONG)TimeFields->Month; /* Put February at the end of the calculation cycle, making leap day handling implicit in the year division */ if(0 >= (LONG)(Month -= 2)) { /* Adjust month and year */ Month += 12; Year -= 1; } /* Calculate absolute elapsed days */ ElapsedDays = (LONGLONG)(Year/4 - Year/100 + Year/400 + 367*Month/12 + TimeFields->Day) + (LONGLONG)Year*365 - 584725LL; /* Calculate total seconds */ TotalSeconds = (ElapsedDays * TIME_SECONDS_PER_DAY) + ((LONGLONG)TimeFields->Hour * TIME_SECONDS_PER_HOUR) + ((LONGLONG)TimeFields->Minute * TIME_SECONDS_PER_MINUTE) + (LONGLONG)TimeFields->Second; /* Convert to 100-ns intervals and slap milliseconds on top */ XtTime->QuadPart = (TotalSeconds * TIME_TICKS_PER_SECOND) + ((LONGLONG)TimeFields->Milliseconds * TIME_TICKS_PER_MILLISECOND); /* Return success */ return STATUS_SUCCESS; } /** * Converts a 64-bit Unix timestamp into a TIME_FIELDS calendar structure. * * @param UnixTime * Supplies a pointer to a 64-bit integer that contains the number of * seconds elapsed since January 1, 1970. * * @param TimeFields * Supplies a pointer to a TIME_FIELDS structure that receives the converted calendar data. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::Time::UnixEpochToTimeFields(IN PLONGLONG UnixTime, OUT PTIME_FIELDS TimeFields) { LONG CalculatedDay, CalculatedMonth, CalculatedYear; LONGLONG Era, SecondsOfDay, TotalSeconds, UnixDays; ULONG DayOfEra, DayOfYear, YearOfEra; /* Validate pointers */ if(UnixTime == NULLPTR || TimeFields == NULLPTR) { /* Invalid pointers provided, return error code */ return STATUS_INVALID_PARAMETER; } /* Extract total seconds */ TotalSeconds = *UnixTime; /* Check sign */ if(TotalSeconds >= 0) { /* Divide TotalSeconds by seconds per day and compute the remainder */ UnixDays = TotalSeconds / TIME_SECONDS_PER_DAY; SecondsOfDay = TotalSeconds % TIME_SECONDS_PER_DAY; } else { /* Subtract seconds per day minus one from TotalSeconds and divide by seconds per day */ UnixDays = (TotalSeconds - (TIME_SECONDS_PER_DAY - 1)) / TIME_SECONDS_PER_DAY; SecondsOfDay = TotalSeconds % TIME_SECONDS_PER_DAY; /* Check if SecondsOfDay is less than zero */ if(SecondsOfDay < 0) { /* Add seconds per day to SecondsOfDay */ SecondsOfDay += TIME_SECONDS_PER_DAY; } } /* Unix timestamps do not natively support milliseconds */ TimeFields->Milliseconds = 0; /* Shift epoch from 1970-01-01 to 0000-03-01 to align with leap year cycles */ UnixDays += 719468LL; /* Calculate the 400-year era */ Era = (UnixDays >= 0 ? UnixDays : UnixDays - 146096) / 146097; /* Calculate the day within the current era */ DayOfEra = (ULONG)(UnixDays - Era * 146097); /* Calculate the year within the current era */ YearOfEra = (DayOfEra - (DayOfEra / 1460) + (DayOfEra / 36524) - (DayOfEra / 146096)) / 365; /* Combine era and year-of-era to get the absolute year */ CalculatedYear = (LONG)(YearOfEra + Era * 400); /* Calculate the day of the year */ DayOfYear = DayOfEra - (365 * YearOfEra + (YearOfEra / 4) - (YearOfEra / 100)); /* Calculate the month */ CalculatedMonth = (5 * DayOfYear + 2) / 153; /* Calculate the exact day of the month */ CalculatedDay = DayOfYear - (153 * CalculatedMonth + 2) / 5 + 1; /* Shift the month back to the standard Gregorian calendar */ CalculatedMonth += (CalculatedMonth < 10 ? 3 : -9); /* If the month is January or February, it belongs to the next computational year */ CalculatedYear += (CalculatedMonth <= 2 ? 1 : 0); /* Validate computed year */ if(CalculatedYear < 0 || CalculatedYear > 30827) { /* Year is out of bounds, return error code */ return STATUS_NOT_SUPPORTED; } /* Populate the output structure */ TimeFields->Day = (SHORT)CalculatedDay; TimeFields->Month = (SHORT)CalculatedMonth; TimeFields->Year = (SHORT)CalculatedYear; TimeFields->Hour = (SHORT)(SecondsOfDay / TIME_SECONDS_PER_HOUR); TimeFields->Minute = (SHORT)((SecondsOfDay % TIME_SECONDS_PER_HOUR) / TIME_SECONDS_PER_MINUTE); TimeFields->Second = (SHORT)(SecondsOfDay % TIME_SECONDS_PER_MINUTE); TimeFields->Milliseconds = 0; TimeFields->Weekday = (SHORT)(((UnixDays + 4) % 7 + 7) % 7); /* Return success */ return STATUS_SUCCESS; } /** * Converts a 64-bit XT timestamp into a TIME_FIELDS calendar structure. * * @param XtTime * Supplies a pointer to a variable that contains the time value in * 100-nanosecond intervals since January 1, 1601. * * @param TimeFields * Supplies a pointer to a TIME_FIELDS structure that receives the converted calendar data. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::Time::XtEpochToTimeFields(IN PLARGE_INTEGER XtTime, OUT PTIME_FIELDS TimeFields) { ULONG CurrentYear, Days, Leap, Periods1Year, Periods4Years, Periods100Years, Periods400Years; ULONGLONG TotalSeconds, ElapsedDays, TotalSecondsOfDay; /* Validate pointers */ if(XtTime == NULLPTR || TimeFields == NULLPTR) { /* Invalid pointers provided, return error code */ return STATUS_INVALID_PARAMETER; } /* The XT Epoch starts at 1601, negative absolute system time is not supported */ if(XtTime->QuadPart < 0) { /* Invalid time value, return error code */ return STATUS_INVALID_PARAMETER; } /* Extract ticks into whole seconds and remaining milliseconds */ TotalSeconds = XtTime->QuadPart / TIME_TICKS_PER_SECOND; TimeFields->Milliseconds = (SHORT)((XtTime->QuadPart % TIME_TICKS_PER_SECOND) / TIME_TICKS_PER_MILLISECOND); /* Split total seconds into absolute elapsed days and time of the current day */ ElapsedDays = TotalSeconds / TIME_SECONDS_PER_DAY; TotalSecondsOfDay = TotalSeconds % TIME_SECONDS_PER_DAY; /* Calculate hour, minute, and second */ TimeFields->Hour = (SHORT)(TotalSecondsOfDay / TIME_SECONDS_PER_HOUR); TimeFields->Minute = (SHORT)((TotalSecondsOfDay % TIME_SECONDS_PER_HOUR) / TIME_SECONDS_PER_MINUTE); TimeFields->Second = (SHORT)(TotalSecondsOfDay % TIME_SECONDS_PER_MINUTE); /* Calculate weekday */ TimeFields->Weekday = (SHORT)((ElapsedDays + 1) % 7); /* Calculate the year using the Gregorian leap year cycles */ Days = (ULONG)ElapsedDays; CurrentYear = 1601; /* Calculate completed 400-year periods */ Periods400Years = Days / 146097; CurrentYear += Periods400Years * 400; Days %= 146097; /* Calculate completed 100-year periods */ Periods100Years = Days / 36524; if(Periods100Years == 4) { /* The leap year at the very end of a 400-year cycle */ Periods100Years = 3; } /* Update the current year and remaining days */ CurrentYear += Periods100Years * 100; Days -= Periods100Years * 36524; /* Calculate completed 4-year periods */ Periods4Years = Days / 1461; CurrentYear += Periods4Years * 4; Days %= 1461; /* Calculate completed 1-year periods */ Periods1Year = Days / 365; if(Periods1Year == 4) { /* The leap year at the end of a normal 4-year cycle */ Periods1Year = 3; } /* Update the current year and remaining days */ CurrentYear += Periods1Year; Days -= Periods1Year * 365; /* Set the calculated year */ TimeFields->Year = (SHORT)CurrentYear; /* Check if the calculated year is a leap year */ Leap = LeapYear(TimeFields->Year) ? 1 : 0; TimeFields->Month = 1; /* Subtract days of each month to find the current month */ while(Days >= DaysInMonth[Leap][TimeFields->Month - 1]) { /* Calculate the days of the current month and advance the month index */ Days -= DaysInMonth[Leap][TimeFields->Month - 1]; TimeFields->Month++; } /* Store the remainder as the 1-based day of the month */ TimeFields->Day = (SHORT)(Days + 1); /* Return success */ return STATUS_SUCCESS; } ================================================ FILE: xtoskrnl/rtl/widestr.cc ================================================ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/widestr.cc * DESCRIPTION: Wide string support * DEVELOPERS: Rafal Kupiec */ #include /** * Compares at most specified number of characters of two C wide strings. * * @param String1 * Wide string to be compared. * * @param String2 * Wide string to be compared. * * @param Length * Maximum number of characters to compare. If no limit set, it compares whole wide strings. * * @return Integral value indicating the relationship between the wide strings. * * @since XT 1.0 */ XTAPI SIZE_T RTL::WideString::CompareWideString(IN PCWSTR String1, IN PCWSTR String2, IN SIZE_T Length) { SIZE_T Index; /* Iterate through the strings */ for(Index = 0; ; Index++) { /* Check if length limit reached */ if(Index != 0 && Index == Length) { /* Skip checking next characters */ break; } /* Check if wide string characters are equal */ if(String1[Index] != String2[Index]) { /* Different characters found */ return String1[Index] < String2[Index] ? -1 : 1; } /* Check if end of wide string reached */ if(!String1[Index] || !String2[Index]) { /* Equal wide strings until the end of one of them */ return 0; } } /* Wide strings are equal */ return 0; } /** * Compares at most specified number of characters of two C wide strings, while ignoring differences in case. * * @param String1 * Wide string to be compared. * * @param String2 * Wide string to be compared. * * @param Length * Maximum number of characters to compare. If no limit set, it compares whole wide strings. * * @return Integral value indicating the relationship between the wide strings. * * @since XT 1.0 */ XTAPI SIZE_T RTL::WideString::CompareWideStringInsensitive(IN PCWSTR String1, IN PCWSTR String2, IN SIZE_T Length) { WCHAR Character1; WCHAR Character2; ULONG Index = 0; /* Iterate through the wide strings */ while(String1[Index] != L'\0' && String2[Index] != L'\0') { /* Check if length limit reached */ if(Index != 0 && Index == Length) { /* Skip checking next characters */ break; } /* Get the characters */ Character1 = String1[Index]; Character2 = String2[Index]; /* Lowercase wide string1 character if needed */ if(String1[Index] >= L'A' && String1[Index] <= L'Z') { Character1 = String1[Index] - L'A' + L'a'; } /* Lowercase wide string2 character if needed */ if(String2[Index] >= L'A' && String2[Index] <= L'Z') { Character2 = String2[Index] - L'A' + L'a'; } /* Compare the characters */ if(Character1 != Character2) { /* Wide strings are not equal */ return Character1 > Character2 ? 1 : -1; } /* Get next character */ Index++; } /* Strings are equal */ return 0; } /** * Appends a copy of the source wide string to the end of the destination wide string. * * @param Destination * Supplies a pointer to the NULL-terminated wide string to append to. * * @param Source * Supplies a pointer to the NULL-terminated wide string to copy from. * * @param Count * Sets a maximum number of wide characters to copy. If no limit set, appends whole wide string. * * @return This routine returns a copy of a destination wide string. * * @since XT 1.0 */ XTAPI PWCHAR RTL::WideString::ConcatenateWideString(OUT PWCHAR Destination, IN PWCHAR Source, IN SIZE_T Count) { PWCHAR DestString = Destination; /* Go to the end of destination wide string */ while(*Destination) { Destination++; } /* Check if copy limit set */ if(Count > 0) { /* Copy character-by-character */ do { /* Check if NULL terminated character found */ if((*Destination = *Source++) == L'\0') { /* Break on '\0' character */ break; } Destination++; } while(--Count != 0); /* Add NULL termination character to the end of destination wide string */ *Destination = L'\0'; } else { /* No limit set, copy all wide characters */ while((*Destination++ = *Source++) != 0); } /* Return copy of the destination wide string */ return DestString; } /** * Copies a wide string from a buffer into another buffer, ensuring that the destination string is NULL-terminated. * * @param Destination * Supplies a pointer to the destination buffer. * * @param Source * Supplies a pointer to the source buffer. * * @param Length * Supplies the length of the wide string to copy. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID RTL::WideString::CopyWideString(IN PWCHAR Destination, IN PCWSTR Source, IN ULONG Length) { ULONG Index; /* Copy characters */ for(Index = 0; Index < Length; Index++) { /* Copy source character */ Destination[Index] = Source[Index]; /* Check if NULL terminated character found */ if(Source[Index] == L'\0') { /* End of source string reached */ break; } } /* Make sure the destination string is terminated properly */ Destination[Index] = L'\0'; } /** * Finds the first occurrence of the search wide string in the source wide string. * * @param Source * Supplies a pointer to the source wide string. * * @param Search * Supplies a pointer to the search wide string. * * @return This routine returns a pointer to the first occurrence of the search wide string in the source wide string. * * @since XT 1.0 */ XTAPI PCWSTR RTL::WideString::FindWideString(IN PCWSTR Source, IN PCWSTR Search) { PCWSTR CurrentSource; PCWSTR CurrentSearch; /* Validate input parameters */ if(!Source || !Search) { /* Invalid input parameters, return NULLPTR */ return NULLPTR; } /* Check if search string is empty */ if(*Search == L'\0') { /* Return the source string */ return Source; } /* Iterate through the source string */ for(; *Source != L'\0'; Source++) { /* Initialize pointers */ CurrentSource = Source; CurrentSearch = Search; /* Check if the substring matches starting at the current position */ while(*CurrentSource != L'\0' && *CurrentSearch != L'\0' && *CurrentSource == *CurrentSearch) { /* Go to the next character */ CurrentSource++; CurrentSearch++; } /* If we reached the end of Search string, it is a match */ if(*CurrentSearch == L'\0') { /* Return the source position */ return Source; } } /* No match found, return NULLPTR */ return NULLPTR; } /** * Finds the first case-insensitive occurrence of the search wide string in the source wide string. * * @param Source * Supplies a pointer to the source wide string. * * @param Search * Supplies a pointer to the search wide string. * * @return This routine returns a pointer to the first occurrence of the search wide string in the source wide string. * * @since XT 1.0 */ XTAPI PCWSTR RTL::WideString::FindWideStringInsensitive(IN PCWSTR Source, IN PCWSTR Search) { PCWSTR CurrentSource; PCWSTR CurrentSearch; /* Validate input parameters */ if(!Source || !Search) { /* Invalid input parameters, return NULLPTR */ return NULLPTR; } /* Check if search string is empty */ if(*Search == L'\0') { /* Return the source string */ return Source; } /* Iterate through the source string */ for(; *Source != L'\0'; Source++) { /* Initialize pointers */ CurrentSource = Source; CurrentSearch = Search; /* Check if the substring matches starting at the current position */ while(*CurrentSource != L'\0' && *CurrentSearch != L'\0' && ToLowerWideCharacter(*CurrentSource) == ToLowerWideCharacter(*CurrentSearch)) { /* Go to the next character */ CurrentSource++; CurrentSearch++; } /* If we reached the end of Search string, it is a match */ if(*CurrentSearch == L'\0') { /* Return the source position */ return Source; } } /* No match found, return NULLPTR */ return NULLPTR; } /** * Formats a wide string according to the given printf-alike format string and a list of arguments. * * @param Context * Supplies a pointer to the print context structure. * * @param Format * Supplies a pointer to the printf-alike format string. * * @param ArgumentList * Supplies a list of arguments to the format string. * * @param Index * Supplies a pointer to the position of the current format specifier, that will be advanced beyond the specifier. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::WideString::FormatArgumentSpecifier(IN PRTL_PRINT_CONTEXT Context, IN PCWSTR Format, IN PVA_LIST ArgumentList, IN OUT PULONG Index) { RTL_PRINT_FORMAT_PROPERTIES FormatProperties; PUNICODE_STRING UnicodeStrArg; WCHAR Specifier, WideCharArg; PANSI_STRING AnsiStrArg; LONGLONG SpecifierValue; VA_LIST ArgumentsCopy; LARGE_DOUBLE FloatArg; PCWSTR FormatIndex; ULONG ArgPosition; PCWSTR WideStrArg; ULONGLONG IntArg; XTSTATUS Status; PGUID GuidArg; PCHAR StrArg; CHAR CharArg; /* Set current format specifier index and custom argument position */ FormatIndex = Format + *Index + 1; ArgPosition = 0; /* Initialize format properties */ RTL::Memory::ZeroMemory(&FormatProperties, sizeof(RTL_PRINT_FORMAT_PROPERTIES)); FormatProperties.IntegerSize = sizeof(INT); FormatProperties.Precision = -1; /* Make a copy of the argument list */ VA_COPY(ArgumentsCopy, *ArgumentList); /* Lookup parameter field */ if((*FormatIndex >= L'1') && (*FormatIndex <= L'9')) { /* POSIX extension found, read its value */ SpecifierValue = GetSpecifierValue((PWSTR*)&FormatIndex); /* Make sure parameter field ends with '$' character */ if(*FormatIndex == L'$') { /* Store number of parameter and increment index */ ArgPosition = (ULONG)SpecifierValue; FormatIndex++; } else { /* Field not ended with '$' character, treat it as width field */ FormatProperties.FieldWidth = (ULONG)SpecifierValue; } } /* Lookup flags field */ while(TRUE) { /* Look for a valid flag and set properties */ if(*FormatIndex == L'\'') { /* Thousands grouping separator applied */ FormatProperties.Flags |= PFL_THOUSANDS_GROUPING; } else if(*FormatIndex == L'-') { /* Left-align the output */ FormatProperties.Flags |= PFL_LEFT_JUSTIFIED; } else if(*FormatIndex == L' ') { /* Prepend a space for positive signed-numeric types */ FormatProperties.Flags |= PFL_SPACE_FOR_PLUS; } else if(*FormatIndex == L'+') { /* Prepend a plus for positive signed-numeric types */ FormatProperties.Flags |= PFL_ALWAYS_PRINT_SIGN; } else if(*FormatIndex == L'#') { /* Convert to an alternate form */ FormatProperties.Flags |= PFL_PRINT_RADIX; } else if(*FormatIndex == L'0') { /* Prepend zeros for numeric types */ FormatProperties.Flags |= PFL_LEADING_ZEROES; } else { /* No more flags to read */ break; } /* Move to the next character */ FormatIndex++; } /* Check if output is left-justified */ if(FormatProperties.Flags & PFL_LEFT_JUSTIFIED) { /* Left justified output can't have leading zeros */ FormatProperties.Flags &= ~PFL_LEADING_ZEROES; } /* Check if plus for positive signed-numeric types is enabled */ if(FormatProperties.Flags & PFL_ALWAYS_PRINT_SIGN) { /* Do not append a space when plus character is enabled */ FormatProperties.Flags &= ~PFL_SPACE_FOR_PLUS; } /* Lookup width field */ if(*FormatIndex == L'*') { /* Skip dynamic width field indicator */ FormatIndex++; /* Read dynamic width value from the argument list */ FormatProperties.FieldWidth = VA_ARG(*ArgumentList, INT); } else if((*FormatIndex >= L'1') && (*FormatIndex <= L'9')) { /* Read a numeric width value */ FormatProperties.FieldWidth = GetSpecifierValue((PWSTR*)&FormatIndex); } /* Check if field width is set to negative value */ if(FormatProperties.FieldWidth < 0) { /* Force left-aligned output and turn field width into positive value */ FormatProperties.Flags |= PFL_LEFT_JUSTIFIED; FormatProperties.FieldWidth *= -1; } /* Lookup precision field */ if(*FormatIndex == L'.') { /* Skip precision field indicator */ FormatIndex++; /* Look for a dynamic precision value indicator */ if(*FormatIndex == L'*') { /* Read dynamic precision value from the argument list */ FormatIndex++; FormatProperties.Precision = VA_ARG(*ArgumentList, INT); } else if((*FormatIndex >= L'0') && (*FormatIndex <= L'9')) { /* Read a numeric precision value */ FormatProperties.Precision = GetSpecifierValue((PWSTR*)&FormatIndex); } else { /* Set default precision */ FormatProperties.Precision = 0; } } /* Check if precision is set to negative value */ if(FormatProperties.Precision < 0) { /* Disable precision */ FormatProperties.Precision = -1; } /* Lookup argument length modifier */ Specifier = *FormatIndex; switch(Specifier) { case L'h': /* SHORT-sized integer argument */ FormatIndex++; FormatProperties.IntegerSize = sizeof(SHORT); FormatProperties.Flags |= PFL_SHORT_VALUE; if(*FormatIndex == L'h') { /* CHAR-sized integer argument */ FormatIndex++; FormatProperties.IntegerSize = sizeof(CHAR); FormatProperties.Flags &= ~PFL_SHORT_VALUE; } break; case L'j': /* INTMAX-sized integer argument */ FormatIndex++; FormatProperties.IntegerSize = sizeof(LONG_PTR); break; case L'l': /* LONG-sized double/integer argument */ FormatIndex++; FormatProperties.IntegerSize = sizeof(LONG); FormatProperties.Flags |= PFL_LONG_DOUBLE | PFL_LONG_INTEGER | PFL_WIDE_CHARACTER; if(*FormatIndex == L'l') { /* LONGLONG-sized integer argument */ FormatIndex++; FormatProperties.IntegerSize = sizeof(LONGLONG); FormatProperties.Flags &= ~(PFL_LONG_DOUBLE | PFL_LONG_INTEGER | PFL_WIDE_CHARACTER); } break; case L'q': /* BSD extension: 64-bit (quad word) integer argument */ FormatIndex++; FormatProperties.IntegerSize = sizeof(LONGLONG); break; case L't': /* PTRDIFF-sized integer argument */ FormatIndex++; FormatProperties.IntegerSize = sizeof(PVOID); break; case L'w': /* MSVC extension: wide character or wide string argument */ FormatIndex++; FormatProperties.Flags |= PFL_WIDE_CHARACTER; break; case L'z': /* SIZE_T-sized integer argument */ FormatIndex++; FormatProperties.IntegerSize = sizeof(SIZE_T); break; case L'I': /* MSVC extension: SIZE_T-sized integer argument */ FormatIndex++; FormatProperties.IntegerSize = sizeof(SIZE_T); if((*FormatIndex == L'3') && (*(FormatIndex + 1) == L'2')) { /* MSVC extension: 32-bit (double word) integer argument */ FormatIndex += 2; FormatProperties.IntegerSize = sizeof(LONG); FormatProperties.Flags |= PFL_LONG_INTEGER; } else if((*FormatIndex == L'6') && (*(FormatIndex + 1) == L'4')) { /* MSVC extension: 64-bit (quad word) integer argument */ FormatIndex += 2; FormatProperties.IntegerSize = sizeof(LONGLONG); } break; case L'L': /* LONG-sized double argument */ FormatIndex++; FormatProperties.IntegerSize = sizeof(LDOUBLE); FormatProperties.Flags |= PFL_LONG_DOUBLE; break; } /* Lookup format specifier */ Specifier = *FormatIndex++; /* Handle char and string modifiers */ if(FormatProperties.Flags & PFL_WIDE_CHARACTER) { if(Specifier == L'c') { /* Wide character argument */ Specifier = L'C'; } else if(Specifier == L's') { /* Wide string argument */ Specifier = L'S'; } } /* Lookup format specifier */ FormatProperties.Flags |= PFL_UNSIGNED; switch(Specifier) { case L'a': /* Double argument as hexadecimal number (lowercase) */ FormatProperties.VariableType = TypeFloat; FormatProperties.Flags |= PFL_SCI_FORMAT; FormatProperties.Radix = 16; break; case L'A': /* Double argument as hexadecimal number (uppercase) */ FormatProperties.VariableType = TypeFloat; FormatProperties.Flags |= PFL_SCI_FORMAT | PFL_UPPERCASE; FormatProperties.Radix = 16; break; case L'b': /* XTOS extension: Boolean argument (lowercase) */ FormatProperties.VariableType = TypeBoolean; break; case L'B': /* XTOS extension: Boolean argument (uppercase) */ FormatProperties.VariableType = TypeBoolean; FormatProperties.Flags |= PFL_UPPERCASE; break; case L'c': /* Character argument */ FormatProperties.VariableType = TypeChar; break; case L'C': /* Wide character argument */ FormatProperties.VariableType = TypeWideChar; break; case L'd': case L'i': /* Signed integer argument as decimal number */ FormatProperties.VariableType = TypeInteger; FormatProperties.Flags &= ~PFL_UNSIGNED; FormatProperties.Radix = 10; break; case L'e': /* Double argument in scientific notation (lowercase) */ FormatProperties.VariableType = TypeFloat; FormatProperties.Flags |= PFL_SCI_FORMAT; break; case L'E': /* Double argument in scientific notation (uppercase) */ FormatProperties.VariableType = TypeFloat; FormatProperties.Flags |= PFL_SCI_FORMAT | PFL_UPPERCASE; break; case L'f': /* Double argument as floating point number (lowercase) */ FormatProperties.VariableType = TypeFloat; FormatProperties.Flags |= PFL_FLOAT_FORMAT; break; case L'F': /* Double argument as floating point number (uppercase) */ FormatProperties.VariableType = TypeFloat; FormatProperties.Flags |= PFL_FLOAT_FORMAT | PFL_UPPERCASE; break; case L'g': /* Double argument as either floating point number or in scientific notation (lowercase) */ FormatProperties.VariableType = TypeFloat; FormatProperties.Flags |= PFL_DIGIT_PRECISION; break; case L'G': /* Double argument as either floating point number or in scientific notation (uppercase) */ FormatProperties.VariableType = TypeFloat; FormatProperties.Flags |= PFL_DIGIT_PRECISION | PFL_UPPERCASE; break; case L'n': /* Write number of characters written so far into an integer pointer parameter */ FormatProperties.VariableType = TypeInteger; FormatProperties.IntegerSize = sizeof(PVOID); break; case L'o': /* Unsigned integer argument as octal number */ FormatProperties.VariableType = TypeInteger; FormatProperties.Radix = 8; break; case L'p': /* Pointer argument as hexadecimal number (lowercase) */ FormatProperties.VariableType = TypeInteger; FormatProperties.IntegerSize = sizeof(UINT_PTR); FormatProperties.Flags |= PFL_PRINT_RADIX; FormatProperties.Radix = 16; break; case L'P': /* XTOS extension: Pointer argument as hexadecimal number (uppercase) */ FormatProperties.VariableType = TypeInteger; FormatProperties.IntegerSize = sizeof(UINT_PTR); FormatProperties.Flags |= PFL_PRINT_RADIX | PFL_UPPERCASE; FormatProperties.Radix = 16; break; case L's': /* String argument */ FormatProperties.VariableType = TypeString; break; case L'S': /* Wide string argument */ FormatProperties.VariableType = TypeWideString; break; case L'u': /* Unsigned integer argument as decimal number */ FormatProperties.VariableType = TypeInteger; FormatProperties.Radix = 10; break; case L'v': /* XTOS extension: UUID/GUID argument (lowercase) */ FormatProperties.VariableType = TypeGuid; break; case L'V': /* XTOS extension: UUID/GUID argument (uppercase) */ FormatProperties.VariableType = TypeGuid; FormatProperties.Flags |= PFL_UPPERCASE; break; case L'x': /* Unsigned integer argument as hexadecimal number (lowercase) */ FormatProperties.VariableType = TypeInteger; FormatProperties.Radix = 16; break; case L'X': /* Unsigned integer argument as hexadecimal number (uppercase) */ FormatProperties.VariableType = TypeInteger; FormatProperties.Flags |= PFL_UPPERCASE; FormatProperties.Radix = 16; break; case L'Z': /* MSVC extension: ANSI/Unicode string argument */ FormatProperties.VariableType = (FormatProperties.Flags & PFL_WIDE_CHARACTER) ? TypeUnicodeString : TypeAnsiString; break; case L'%': /* Print '%' character */ FormatProperties.VariableType = TypeUnknown; WideCharArg = L'%'; break; default: /* Unknown format specifier, print '?' character */ FormatProperties.VariableType = TypeUnknown; WideCharArg = L'?'; break; } /* Finally, write the formatted argument */ if(FormatProperties.VariableType == TypeUnknown) { /* Write defined wide character */ Status = WriteValue(Context, &FormatProperties, &WideCharArg, 1); } if(FormatProperties.VariableType == TypeBoolean) { /* Boolean type */ if(ArgPosition != 0) { /* Get argument value from specified argument position */ IntArg = GetArgument(&ArgumentsCopy, ArgPosition, FormatProperties.IntegerSize); } else { /* Get argument value from the next argument */ IntArg = VA_ARG(*ArgumentList, ULONGLONG); } /* Check if using uppercase format */ if(FormatProperties.Flags & PFL_UPPERCASE) { /* Set uppercase boolean string depending on argument value */ WideStrArg = IntArg ? L"TRUE" : L"FALSE"; } else { /* Set lowercase boolean string depending on argument value */ WideStrArg = IntArg ? L"true" : L"false"; } /* Write formatted boolean string */ Status = WriteValue(Context, &FormatProperties, WideStrArg, WideStringLength(WideStrArg, 0)); } else if(FormatProperties.VariableType == TypeGuid) { /* GUID type */ if(ArgPosition != 0) { /* Get argument value from specified argument position */ IntArg = GetArgument(&ArgumentsCopy, ArgPosition, sizeof(PGUID)); GuidArg = (PGUID)(UINT_PTR)IntArg; } else { /* Get argument value from the next argument */ GuidArg = VA_ARG(*ArgumentList, PGUID); } /* Make sure a pointer to GUID is not NULL pointer */ if(GuidArg != NULLPTR) { /* Check if using uppercase format */ if(FormatProperties.Flags & PFL_UPPERCASE) { /* Use uppercase GUID format string */ WideStrArg = L"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"; } else { /* Use lowercase GUID format string */ WideStrArg = L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"; } /* Write formatted GUID string */ Status = WriteCustomValue(Context, WideStrArg, GuidArg->Data1, GuidArg->Data2, GuidArg->Data3, GuidArg->Data4[0], GuidArg->Data4[1], GuidArg->Data4[2], GuidArg->Data4[3], GuidArg->Data4[4], GuidArg->Data4[5], GuidArg->Data4[6], GuidArg->Data4[7]); } } else if(FormatProperties.VariableType == TypeChar) { /* Character type */ if(ArgPosition != 0) { /* Get argument value from specified argument position */ CharArg = (UCHAR)GetArgument(&ArgumentsCopy, ArgPosition, sizeof(UCHAR)); } else { /* Get argument value from the next argument */ CharArg = VA_ARG(*ArgumentList, INT); } /* Write formatted character */ Status = WriteStringValue(Context, &FormatProperties, &CharArg, 1); } else if(FormatProperties.VariableType == TypeWideChar) { /* Wide character type */ if(ArgPosition != 0) { /* Get argument value from specified argument position */ WideCharArg = (WCHAR)GetArgument(&ArgumentsCopy, ArgPosition, sizeof(WCHAR)); } else { /* Get argument value from the next argument */ WideCharArg = VA_ARG(*ArgumentList, INT); } /* Write formatted wide character */ Status = WriteValue(Context, &FormatProperties, &WideCharArg, 1); } else if(FormatProperties.VariableType == TypeFloat) { /* Float/Double type */ if(ArgPosition != 0) { /* Get argument value from specified argument position */ FloatArg.QuadPart = GetArgument(&ArgumentsCopy, ArgPosition, sizeof(ULONGLONG)); } else { /* Get argument value from the next argument, depending on its size */ if(FormatProperties.Flags & PFL_LONG_DOUBLE) { FloatArg.DoublePart = VA_ARG(*ArgumentList, LDOUBLE); } else { FloatArg.DoublePart = VA_ARG(*ArgumentList, DOUBLE); } } /* Write formatted double value */ Status = WriteDoubleValue(Context, &FormatProperties, FloatArg.DoublePart); } else if(FormatProperties.VariableType == TypeInteger) { /* Integer type */ if(ArgPosition != 0) { /* Get argument value from specified argument position */ IntArg = GetArgument(&ArgumentsCopy, ArgPosition, FormatProperties.IntegerSize); /* Convert to required integer size */ switch(FormatProperties.IntegerSize) { case sizeof(CHAR): IntArg = (UCHAR)IntArg; break; case sizeof(SHORT): IntArg = (USHORT)IntArg; break; case sizeof(LONG): IntArg = (ULONG)IntArg; break; case sizeof(LONGLONG): IntArg = (ULONGLONG)IntArg; break; default: return STATUS_INVALID_PARAMETER; } } else { /* Get argument value from the next argument, depending on its size */ switch(FormatProperties.IntegerSize) { case sizeof(CHAR): IntArg = (CHAR)VA_ARG(*ArgumentList, UINT); break; case sizeof(SHORT): IntArg = (SHORT)VA_ARG(*ArgumentList, UINT); break; case sizeof(LONG): IntArg = VA_ARG(*ArgumentList, ULONG); break; case sizeof(LONGLONG): IntArg = VA_ARG(*ArgumentList, ULONGLONG); break; default: return STATUS_INVALID_PARAMETER; } } /* Check if using 'n' specifier */ if(Specifier == L'n') { /* Make sure, that integer pointer parameter is not NULL */ if(IntArg != (UINT_PTR)NULLPTR) { /* Store number of characters written in integer pointer parameter */ *((PINT)(UINT_PTR)IntArg) = Context->CharactersWritten; } } else { /* Write formatted integer value */ Status = WriteIntegerValue(Context, &FormatProperties, IntArg); } } else if(FormatProperties.VariableType == TypeString) { /* String type */ if(ArgPosition != 0) { /* Get argument value from specified argument position */ IntArg = GetArgument(&ArgumentsCopy, ArgPosition, sizeof(PCHAR)); StrArg = (PCHAR)(UINT_PTR)IntArg; } else { /* Get argument value from the next argument */ StrArg = VA_ARG(*ArgumentList, PCHAR); } /* Write formatted string value */ Status = WriteStringValue(Context, &FormatProperties, StrArg, RTL::String::StringLength(StrArg, 0)); } else if(FormatProperties.VariableType == TypeWideString) { /* Wide string type */ if(ArgPosition != 0) { /* Get argument value from specified argument position */ IntArg = GetArgument(&ArgumentsCopy, ArgPosition, sizeof(PWCHAR)); WideStrArg = (PCWSTR)(UINT_PTR)IntArg; } else { /* Get argument value from the next argument */ WideStrArg = VA_ARG(*ArgumentList, PWCHAR); } /* Write formatted wide string value */ Status = WriteValue(Context, &FormatProperties, WideStrArg, RtlWideStringLength(WideStrArg, 0)); } else if(FormatProperties.VariableType == TypeAnsiString ) { /* ANSI string type */ if(ArgPosition != 0) { /* Get argument value from specified argument position */ IntArg = GetArgument(&ArgumentsCopy, ArgPosition, sizeof(PANSI_STRING)); AnsiStrArg = (PANSI_STRING)(UINT_PTR)IntArg; } else { /* Get argument value from the next argument */ AnsiStrArg = VA_ARG(*ArgumentList, PANSI_STRING); } /* Make sure a pointer to ANSI_STRING is not NULL */ if(AnsiStrArg != NULLPTR) { /* Write formatted ANSI string value */ Status = WriteStringValue(Context, &FormatProperties, AnsiStrArg->Buffer, AnsiStrArg->Length); } } else if(FormatProperties.VariableType == TypeUnicodeString) { /* Unicode string type */ if(ArgPosition != 0) { /* Get argument value from specified argument position */ IntArg = GetArgument(&ArgumentsCopy, ArgPosition, sizeof(PUNICODE_STRING)); UnicodeStrArg = (PUNICODE_STRING)(UINT_PTR)IntArg; } else { /* Get argument value from the next argument */ UnicodeStrArg = VA_ARG(*ArgumentList, PUNICODE_STRING); } /* Make sure a pointer to UNICODE_STRING is not NULL */ if(UnicodeStrArg != NULLPTR) { /* Write formatted UNICODE string value */ Status = WriteValue(Context, &FormatProperties, UnicodeStrArg->Buffer, UnicodeStrArg->Length); } } /* Cleanup ArgumentsCopy object */ VA_END(ArgumentsCopy); /* Increase index position according to number of characters consumed */ *Index += ((UINT_PTR)FormatIndex - (UINT_PTR)(Format + *Index)) / sizeof(WCHAR); /* Return status code */ return Status; } /** * Formats a wide string according to the given printf-alike format string. * * @param Context * Supplies a pointer to the print context structure. * * @param Format * Supplies a pointer to the printf-alike format string. * * @param ArgumentList * Supplies a list of arguments to the format string. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::WideString::FormatWideString(IN PRTL_PRINT_CONTEXT Context, IN PCWSTR Format, IN VA_LIST ArgumentList) { VA_LIST LocalArgumentList; XTSTATUS Status; ULONG Index; /* Make sure, that we have valid context and write routine */ if(Context == NULLPTR || Context->WriteWideCharacter == NULLPTR) { /* Invalid context or write routine not set */ return FALSE; } /* Check format string pointer */ if(Format == NULLPTR) { /* Write null string */ Format = L"(null)"; } /* Make a copy of the argument list */ VA_COPY(LocalArgumentList, ArgumentList); /* Iterate through format string */ Index = 0; while(Format[Index] != L'\0') { /* Look for format specifier */ if(Format[Index] == L'%') { /* Handle format along with arguments */ Status = FormatArgumentSpecifier(Context, Format, &LocalArgumentList, &Index); } else { /* Write wide character and increase string index */ Status = WriteWideCharacter(Context, Format[Index]); Index++; } /* Make sure character written successfully */ if(Status != STATUS_SUCCESS) { /* Return status code */ return Status; } } /* Clean up the argument list */ VA_END(LocalArgumentList); /* Return success */ return STATUS_SUCCESS; } /** * Gets the positional argument by scanning the argument list. * * @param ArgumentList * Supplies a pointer to the argument list. * * @param ArgumentNumber * Supplies the argument number. * * @param ArgumentSize * Supplies the expected size of the argument. */ XTAPI ULONGLONG RTL::WideString::GetArgument(IN PVA_LIST ArgumentList, IN ULONG ArgumentNumber, IN LONG ArgumentSize) { VA_LIST ArgumentsCopy; ULONGLONG Value; ULONG Index; /* Make a copy of the argument list */ VA_COPY(ArgumentsCopy, *ArgumentList); /* Skip all arguments before the specified one */ for(Index = 1; Index < ArgumentNumber; Index += 1) { /* Skip the argument */ Value = VA_ARG(ArgumentsCopy, LONGLONG); } /* Set default value */ Value = 0; /* Get the argument value depending on its declared size */ switch(ArgumentSize) { case sizeof(CHAR): Value = (UCHAR)VA_ARG(ArgumentsCopy, INT); break; case sizeof(SHORT): Value = (USHORT)VA_ARG(ArgumentsCopy, INT); break; case sizeof(LONG): Value = VA_ARG(ArgumentsCopy, LONG); break; case sizeof(LONGLONG): Value = VA_ARG(ArgumentsCopy, LONGLONG); break; default: Value = 0; break; } /* Cleanup ArgumentsCopy object and return the argument value */ VA_END(ArgumentsCopy); return Value; } /** * Gets the specifier integer value from the wide string advancing the pointer. * * @param Format * Supplies a pointer to the wide string format, at integer value position. * * @return This routine returns a specifier integer value read from wide string format, or zero if no valid value found. * * @since XT 1.0 */ XTAPI ULONGLONG RTL::WideString::GetSpecifierValue(IN PWCHAR *Format) { ULONG Count; PWCHAR Fmt; /* Initialize variables */ Fmt = *Format; Count = 0; /* Read the specifier value */ for(;; Fmt++) { switch(*Fmt) { case L'0' ... L'9': /* Read the number from wide string */ Count = Count * 10 + *Fmt - L'0'; break; default: /* No more numbers, return count */ *Format = Fmt; return Count; } } /* Return zero if no value specified */ return 0; } /** * Reverses a characters order in a wide string. It modifies the original, input variable. * * @param String * Supplies a pointer to the wide string to reverse. * * @param Length * Supplies the length of the wide string to reverse. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID RTL::WideString::ReverseWideString(IN OUT PWCHAR String, IN ULONG Length) { WCHAR TempChar; ULONG Index; /* Iterate through the string */ for(Index = 0; Index < (Length / 2); Index++) { /* Swap characters */ TempChar = String[Index]; String[Index] = String[Length - Index - 1]; String[Length - Index - 1] = TempChar; } } /** * Finds the next token in a NULL-terminated wide string. * * @param String * Pointer to the NULL-terminated wide string to tokenize. * * @param Delimiter * Pointer to the NULL-terminated wide string identifying delimiters. * * @param SavePtr * Pointer to an object used to store routine internal state. * * @return Pointer to the beginning of the next token or NULLPTR if there are no more tokens. * * @since: XT 1.0 */ XTAPI PWCHAR RTL::WideString::TokenizeWideString(IN PWCHAR String, IN PCWSTR Delimiter, IN OUT PWCHAR *SavePtr) { PWCHAR Span, Token; WCHAR Char, SpanChar; /* Check if there is anything to tokenize */ if(String == NULLPTR && (String = *SavePtr) == NULLPTR) { /* Empty string given */ return NULLPTR; } /* Check non-delimiter characters */ Char = *String++; if(Char == L'\0') { *SavePtr = NULLPTR; return NULLPTR; } Token = String - 1; /* Scan token for delimiters */ for(;;) { Char = *String++; Span = (PWCHAR)Delimiter; do { /* Check if delimiter found */ if((SpanChar = *Span++) == Char) { /* Check if end of string reached */ if(Char == L'\0') { /* End of string reached, no more tokens */ String = NULLPTR; } else { /* Terminate token */ String[-1] = L'\0'; } /* Store pointer to the next token */ *SavePtr = String; /* Return token */ return Token; } } while(SpanChar != L'\0'); } } /** * Converts a wide character to lowercase. * * @param Character * Wide character to be converted. * * @return Converted wide character or original character if it was not uppercase. * * @since XT 1.0 */ XTAPI WCHAR RTL::WideString::ToLowerWideCharacter(IN WCHAR Character) { /* Check if wide character is uppercase */ if(Character >= L'A' && Character <= L'Z') { /* Convert wide character to lowercase */ return (WCHAR)(Character + (L'a' - L'A')); } /* Return original wide character */ return Character; } /** * Converts a wide character to uppercase. * * @param Character * Wide character to be converted. * * @return Converted wide character or original character if it was not lowercase. * * @since XT 1.0 */ XTAPI WCHAR RTL::WideString::ToUpperWideCharacter(IN WCHAR Character) { /* Check if wide character is lowercase */ if(Character >= L'a' && Character <= L'z') { /* Convert wide character to uppercase */ return (WCHAR)(Character - (L'a' - L'A')); } /* Return original wide character */ return Character; } /** * Removes certain characters from a beginning of the wide string. * * @param String * Pointer to the NULL-terminated wide string to be trimmed. * * @return This routine returns a pointer to the left-trimmed wide string. * * @since XT 1.0 */ XTAPI PWCHAR RTL::WideString::TrimLeftWideString(IN PWCHAR String) { PWCHAR Start; /* Initialize pointer */ Start = String; /* Skip all leading whitespaces */ while(*Start == L' ' || *Start == L'\n' || *Start == L'\t' || *Start == L'\r' || *Start == L'\v' || *Start == L'\f') { /* Advance to the next character */ Start++; } /* Return left-trimmed string */ return Start; } /** * Removes certain characters from the end of the wide string. * * @param String * Pointer to the NULL-terminated wide string to be trimmed. * * @return This routine returns a pointer to the right-trimmed wide string. * * @since XT 1.0 */ XTAPI PWCHAR RTL::WideString::TrimRightWideString(IN PWCHAR String) { PWCHAR End; /* Find end of the string */ End = String + RtlWideStringLength(String, 0); /* Skip all trailing whitespaces */ while((End != String) && (*End == L' ' || *End == L'\n' || *End == L'\t' || *End == L'\r' || *End == L'\v' || *End == L'\f')) { /* Move to the previous character */ End--; } /* Terminate the string */ *End = 0; /* Return right-trimmed string */ return String; } /** * Removes certain characters from the beginning and the end of the wide string. * * @param String * Pointer to the NULL-terminated wide string to be trimmed. * * @return This routine returns a pointer to the trimmed wide string. * * @since XT 1.0 */ XTAPI PWCHAR RTL::WideString::TrimWideString(IN PWCHAR String) { return RtlTrimLeftWideString(RtlTrimRightWideString(String)); } /** * Calculates the length of a given wide string. * * @param String * Pointer to the NULL-terminated wide string to be examined. * * @param MaxLength * Maximum number of wide characters to examine. If no limit set, it examines whole string. * * @return The length of the NULL-terminated wide string. * * @since: XT 1.0 */ XTAPI SIZE_T RTL::WideString::WideStringLength(IN PCWSTR String, IN SIZE_T MaxLength) { SIZE_T Length; /* Check if NULL pointer passed */ if(String == NULLPTR) { return 0; } /* Iterate through the wide string */ for(Length = 0; ; Length++) { /* Check if NULL found or max length limit reached */ if((Length != 0 && Length == MaxLength) || !String[Length]) { /* Finish examination */ break; } } /* Return wide string length */ return Length; } /** * Converts a wide string to a number. * * @param String * Supplies a pointer to the NULL-terminated wide string to convert. * * @param Base * Supplies the optional numerical base for the conversion (2, 8, 10, or 16). * * @param Value * Supplies a pointer to a variable that receives the converted numeric value. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::WideString::WideStringToNumber(IN PCWSTR String, IN ULONG Base, OUT PULONG Value) { BOOLEAN NegativeValue; ULONG Digit, Result; /* Validate input parameters */ if(!String || !Value) { /* Invalid input parameters, return error code */ return STATUS_INVALID_PARAMETER; } /* Initialize local variables */ NegativeValue = FALSE; Result = 0; /* Skip leading whitespaces and control characters */ while(*String != L'\0' && *String <= L' ') { /* Advance to the next character */ String++; } /* Consume and record sign */ if(*String == L'-') { /* Set negative value flag and advance to the next character */ NegativeValue = TRUE; String++; } else if(*String == L'+') { /* Advance to the next character */ String++; } /* Autodetect and validate the base */ if(Base == 0) { /* Autodetect base based on prefix */ if(String[0] == L'0') { /* Validate prefix */ if(String[1] == L'x' || String[1] == L'X') { /* Hexadecimal base */ Base = 16; String += 2; } else if(String[1] == L'o' || String[1] == L'O') { /* Octal base */ Base = 8; String += 2; } else if(String[1] == L'b' || String[1] == L'B') { /* Binary base */ Base = 2; String += 2; } else { /* Starts with 0 but no known prefix, treat as decimal */ Base = 10; } } else { /* Default to decimal base */ Base = 10; } } else { /* Validate explicitly provided base */ if(Base != 2 && Base != 8 && Base != 10 && Base != 16) { /* Invalid base, return error code */ return STATUS_INVALID_PARAMETER; } /* Check if number starts with 0 */ if(String[0] == L'0') { /* Check for prefix */ if(Base == 16 && (String[1] == L'x' || String[1] == L'X')) { /* Skip hexadecimal prefix */ String += 2; } else if(Base == 8 && (String[1] == L'o' || String[1] == L'O')) { /* Skip octal prefix */ String += 2; } else if(Base == 2 && (String[1] == L'b' || String[1] == L'B')) { /* Skip binary prefix */ String += 2; } } } /* Parse string character by character */ while(*String != L'\0') { /* Convert wide character to numeric digit */ if(*String >= L'0' && *String <= L'9') { /* Convert decimal digit */ Digit = *String - L'0'; } else if(*String >= L'A' && *String <= L'F') { /* Convert hexadecimal digit */ Digit = *String - L'A' + 10; } else if(*String >= L'a' && *String <= L'f') { /* Convert hexadecimal digit */ Digit = *String - L'a' + 10; } else { /* Invalid character for a number encountered, stop parsing */ break; } /* Check if digit is valid for the current base */ if(Digit >= Base) { /* Digit out of range for this base, stop parsing */ break; } /* Check for integer overflow */ if((Result > (MAXULONG / Base)) || ((Result * Base) > (MAXULONG - Digit))) { /* Integer overflow, return error code */ return STATUS_INTEGER_OVERFLOW; } /* Accumulate result */ Result = (Result * Base) + Digit; /* Advance to the next character */ String++; } /* Check for negative value */ if(NegativeValue) { /* Apply sign and return the result */ *Value = (ULONG)(-(LONG)Result); } else { /* Return the result */ *Value = Result; } /* Return success */ return STATUS_SUCCESS; } /** * Writes a wide character to the destination provided by the print context. * * @param Context * Supplies a pointer to the print context structure. * * @param Character * Supplies the wide character to write. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::WideString::WriteWideCharacter(IN PRTL_PRINT_CONTEXT Context, IN WCHAR Character) { XTSTATUS Status; /* Write wide character and increment number of characters written so far */ Status = Context->WriteWideCharacter(Character); Context->CharactersWritten++; /* Return status code */ return Status; } /** * Writes a wide string custom-formatted value to the destination provided by the print context. * * @param Context * Supplies a pointer to the print context structure. * * @param Format * Supplies a pointer to the printf-alike format string. * * @param ... * Depending on the format string, this routine might expect a sequence of additional arguments. * * @return This routine returns a status code. * * @since XT 1.0 */ XTCDECL XTSTATUS RTL::WideString::WriteCustomValue(IN PRTL_PRINT_CONTEXT Context, IN PCWSTR Format, IN ...) { VA_LIST Arguments; XTSTATUS Status; /* Initialise the va_list */ VA_START(Arguments, Format); /* Format and print the string to the desired output */ Status = FormatWideString(Context, Format, Arguments); /* Clean up the va_list */ VA_END(Arguments); /* Return status code */ return Status; } XTAPI XTSTATUS RTL::WideString::WriteDoubleValue(IN PRTL_PRINT_CONTEXT Context, IN PRTL_PRINT_FORMAT_PROPERTIES FormatProperties, IN DOUBLE Value) { LONG CurrentExponent, DigitCount, Exponent, Precision, PrecisionIndex, SignificantDigits; WCHAR Character, Digit, ExponentCharacter, SignCharacter; ULONG FieldCount, FieldIndex, Index, NumberLength; WCHAR Buffer[MAX_DOUBLE_STRING_SIZE]; BOOLEAN NegativeValue, WriteExponent; DOUBLE RoundingAmount, TenPower; PCWSTR NonNumberString; LARGE_DOUBLE Parts; XTSTATUS Status; /* Initialize variables */ NegativeValue = FALSE; NumberLength = 0; Parts.DoublePart = Value; Precision = FormatProperties->Precision; SignCharacter = 0; /* Check if the precision is specified */ if(Precision == -1) { /* Set default precision */ Precision = DOUBLE_PRECISION; } /* Check if the precision is zero */ if((FormatProperties->Flags & PFL_DIGIT_PRECISION) && (Precision == 0)) { /* Display at least one digit */ Precision = 1; } /* Determine whether the value is infinite or nan */ if(RTL::Math::InfiniteDouble(Value)) { /* Check if the value is nan */ if(RTL::Math::NanDouble(Value)) { /* Set non-number string depending on the selection of upper or lowercase */ if(FormatProperties->Flags & PFL_UPPERCASE) { NonNumberString = L"#NAN"; } else { NonNumberString = L"#nan"; } } else { /* Otherwise it is infinite, set proper string depending on the selection of upper or lowercase */ if(FormatProperties->Flags & PFL_UPPERCASE) { NonNumberString = L"#INF"; } else { NonNumberString = L"#inf"; } /* Check if the value is negative */ if(Value < 0) { NegativeValue = TRUE; } } /* Set index to 0 and add sign if needed */ Index = 0; if(NegativeValue != FALSE) { /* Add negative (-) sign */ Buffer[Index] = L'-'; Index++; } else if(FormatProperties->Flags & PFL_ALWAYS_PRINT_SIGN) { /* Add positive (+) sign */ Buffer[Index] = L'+'; Index++; } else if(FormatProperties->Flags & PFL_SPACE_FOR_PLUS) { /* Add space for positive value */ Buffer[Index] = L' '; Index++; } /* Copy string to buffer and write it to wide string context */ CopyWideString(Buffer + Index, NonNumberString, sizeof(Buffer) - Index); return WriteValue(Context, FormatProperties, Buffer, WideStringLength(Buffer, 0)); } /* Check whether we need to handle hexadecimal format */ if(FormatProperties->Radix == 16) { /* Handle it as hex value */ return WriteHexDoubleValue(Context, FormatProperties, Value); } /* Check if the value is negative */ if((Parts.u.HighPart & (DOUBLE_SIGN_BIT >> DOUBLE_HIGH_VALUE_SHIFT)) != 0) { /* Turn the negative value into a positive value */ Value *= -1; NegativeValue = TRUE; } /* Calculate the exponent */ Exponent = RTL::Math::GetBaseExponent(Value, &TenPower); RoundingAmount = 0.5; /* Determine whether or not to write the exponent */ WriteExponent = (BOOLEAN)(FormatProperties->Flags & PFL_SCI_FORMAT); if((WriteExponent == FALSE) && !(FormatProperties->Flags & PFL_FLOAT_FORMAT)) { if((Exponent < DOUBLE_SCIENTIFIC_PRECISION) || (Exponent >= Precision)) { /* Write the exponent */ WriteExponent = TRUE; } } /* Make sure the value is not zero */ DigitCount = 0; if(Value != 0.0) { /* Adjust rounding if needed */ if((WriteExponent != FALSE) || (FormatProperties->Flags & PFL_DIGIT_PRECISION)) { /* Calculate the rounding */ RoundingAmount /= TenPower; /* Check if the precision is specified */ if(FormatProperties->Flags & PFL_DIGIT_PRECISION) { /* Increase rounding amount */ RoundingAmount *= 10.0; } } /* Handle the rounding precision */ for(PrecisionIndex = 0; PrecisionIndex < Precision; PrecisionIndex++) { RoundingAmount *= 0.1; } /* Normalize the value */ Value += RoundingAmount; Value *= TenPower; /* Adjust the value if it is greater than 9 */ if((LONG)Value > 9) { Value *= 0.1; Exponent += 1; } /* Turn numbers into characters */ while((Value != 0.0) && (DigitCount < MAX_DOUBLE_STRING_SIZE)) { Buffer[DigitCount] = (LONG)Value + L'0'; DigitCount += 1; Value = (Value - (double)(LONG)Value) * 10.0; } /* Check if precision matters */ if(FormatProperties->Flags & PFL_DIGIT_PRECISION) { /* Make sure precision is greater than 0 */ if(Precision > 0) { /* Check if number of digit exceeds the precision */ if(DigitCount > Precision) { /* Decrease the number of digits to fit the precision */ DigitCount = Precision; } } } /* Remove zero characters from the end of the string */ while((DigitCount > 1) && (Buffer[DigitCount - 1] == L'0')) { /* Decrease buffer length */ DigitCount -= 1; } } /* Handle the sign character */ if(NegativeValue) { /* Negative value, add the '-' character */ SignCharacter = L'-'; } else if(FormatProperties->Flags & PFL_ALWAYS_PRINT_SIGN) { /* Positive value, add the '+' character */ SignCharacter = L'+'; } else if(FormatProperties->Flags & PFL_SPACE_FOR_PLUS) { /* Positive value, add the ' ' character */ SignCharacter = L' '; } /* Handle the significant digit precision */ SignificantDigits = DigitCount; if(FormatProperties->Flags & PFL_DIGIT_PRECISION) { /* Check if number of digit exceeds the precision */ if(SignificantDigits > Precision) { /* Cap the number of significant digits */ SignificantDigits = Precision; } else if(Precision > SignificantDigits) { /* Cap the precision */ Precision = SignificantDigits; /* Check if an exponent is going to be written and if precision needs to be adjusted for it */ if(!WriteExponent && ((Exponent + 1) > Precision)) { /* Adjust the precision */ Precision = Exponent + 1; } /* Make sure precision is greater than 0 */ if(Precision == 0) { /* Adjust the precision */ Precision = 1; } } } /* Check whether to print a radix */ NumberLength = Precision; if(FormatProperties->Flags & PFL_PRINT_RADIX) { /* Include the radix character */ NumberLength += 1; } else if(FormatProperties->Flags & PFL_DIGIT_PRECISION) { /* Check if an exponent is going to be written */ if(WriteExponent) { /* Make sure precision is greater than 1 */ if(Precision > 1) { /* Include radix character */ NumberLength += 1; } } else { /* Still check if radix character should be written */ if((Exponent < 0) || ((Exponent + 1) - SignificantDigits < 0)) { /* Reserve space for radix character */ NumberLength += 1; } } } else if(Precision != 0) { /* Include the radix character */ NumberLength += 1; } /* Check if an exponent is going to be written */ if(WriteExponent) { /* Ensure there is enough room for the exponent character, sign and digits */ NumberLength += 4; /* Check if precision represents the fractional part only */ if(!(FormatProperties->Flags & PFL_DIGIT_PRECISION)) { /* Add space for one more digit */ NumberLength += 1; } /* Check if the exponent is negative */ if(Exponent < 0) { /* Check if the exponent is less than -100 */ if(Exponent <= -100) { /* Add space for one more digit */ NumberLength += 1; /* Check if the exponent is less than -1000 */ if(Exponent <= -1000) { /* Add space for one more digit */ NumberLength += 1; } } } else { /* Check if the exponent is greater than 100 */ if(Exponent >= 100) { /* Add space for one more digit */ NumberLength += 1; /* Check if the exponent is greater than 1000 */ if(Exponent >= 1000) { /* Add space for one more digit */ NumberLength += 1; } } } } else { if(Exponent >= 0) { /* Not negative */ if(!(FormatProperties->Flags & PFL_DIGIT_PRECISION)) { /*Adjust number length */ NumberLength += Exponent + 1; } } else { /* Negative, add space for additional '0' character*/ NumberLength += 1; /* Check if precision is number of significant digits */ if(FormatProperties->Flags & PFL_DIGIT_PRECISION) { /* Add exponent to the precision */ Precision += (-Exponent) - 1; NumberLength += (-Exponent) - 1; } } } /* Make a room for sign character if any */ if(SignCharacter != 0) { NumberLength += 1; } /* Check if field width is bigger than integer */ FieldCount = 0; if(NumberLength < FormatProperties->FieldWidth) { /* Add field spacing characters */ FieldCount = FormatProperties->FieldWidth - NumberLength; } /* Check if prefix will be written */ if((FormatProperties->Flags & PFL_LEFT_JUSTIFIED) || (FormatProperties->Flags & PFL_LEADING_ZEROES)) { /* Check for a sign character */ if(SignCharacter != 0) { /* Write the sign character */ Status = WriteWideCharacter(Context, SignCharacter); if(Status != STATUS_SUCCESS) { /* Failed to write the character, return status code */ return Status; } } /* Reset the sign character */ SignCharacter = 0; } /* Check if leading zero padding is required and if field is left aligned */ if(!(FormatProperties->Flags & PFL_LEFT_JUSTIFIED) || (FormatProperties->Flags & PFL_LEADING_ZEROES)) { /* Check if leading zero padding is required */ if(FormatProperties->Flags & PFL_LEADING_ZEROES) { /* Write leading zeros */ Character = L'0'; } else { /* Write leading spaces */ Character = L' '; } /* Fill up with leading characters */ for(FieldIndex = 0; FieldIndex < FieldCount; FieldIndex++) { /* Write the leading character */ Status = WriteWideCharacter(Context, Character); if(Status != STATUS_SUCCESS) { /* Failed to write the character, return status code */ return Status; } } /* Reset the field count */ FieldCount = 0; } /* Check if a sign character has already been written */ if(SignCharacter != 0) { /* Write the sign character */ Status = WriteWideCharacter(Context, SignCharacter); if(Status != STATUS_SUCCESS) { /* Failed to write the character, return status code */ return Status; } } /* Check if exponent is to be written */ Index = 0; if(WriteExponent) { /* Check if there is anything to write */ if(DigitCount == 0) { /* No digits, write '0' */ Digit = L'0'; } else { /* Write the first digit */ Digit = Buffer[Index]; Index++; } /* Write the digit */ Status = WriteWideCharacter(Context, Digit); if(Status != STATUS_SUCCESS) { /* Failed to write the character, return status code */ return Status; } /* Check if precision is number of significant digits */ if((FormatProperties->Flags & PFL_DIGIT_PRECISION) && (Precision != 0)) { /* Adjust the precision */ Precision--; } /* Check if radix character should be written */ if((Precision != 0) || (FormatProperties->Flags & PFL_PRINT_RADIX)) { /* Write the radix character */ Status = WriteWideCharacter(Context, L'.'); if(Status != STATUS_SUCCESS) { /* Failed to write the character, return status code */ return Status; } } /* Write more digits up to the precision limit */ for(PrecisionIndex = 0; PrecisionIndex < Precision; PrecisionIndex++) { /* Check if there is anything to write */ if(Index < DigitCount) { /* Write the next digit */ Digit = Buffer[Index]; Index++; } else { /* No more digits, write '0' */ Digit = L'0'; } /* Write the digit */ Status = WriteWideCharacter(Context, Digit); if(Status != STATUS_SUCCESS) { /* Failed to write the character, return status code */ return Status; } } /* Check if exponent should be in uppercase */ if(FormatProperties->Flags & PFL_UPPERCASE) { /* Use uppercase exponent character */ ExponentCharacter = L'E'; } else { /* Use lowercase exponent character */ ExponentCharacter = L'e'; } /* Write the exponent string */ Status = WriteCustomValue(Context, L"%C%+0.2d", ExponentCharacter, Exponent); if(Status != STATUS_SUCCESS) { /* Failed to write the characters, return status code */ return Status; } } else { /* Non scientific format, check if exponent is positive value */ if(Exponent >= 0) { /* Write integral part */ CurrentExponent = Exponent; while(CurrentExponent >= 0) { /* Check if there is anything to write */ if(Index < DigitCount) { /* Write the next digit */ Digit = Buffer[Index]; Index++; } else { /* No more digits, write '0' */ Digit = L'0'; } /* Write the digit */ Status = WriteWideCharacter(Context, Digit); if(Status != STATUS_SUCCESS) { /* Failed to write the character, return status code */ return Status; } /* Check if presition is number of significant digits */ if((FormatProperties->Flags & PFL_DIGIT_PRECISION) && (Precision != 0)) { /* Adjust the precision */ Precision--; } /* Get next exponent character */ CurrentExponent--; } } else { /* Exponent is negative, write '0' */ Status = WriteWideCharacter(Context, L'0'); if(Status != STATUS_SUCCESS) { /* Failed to write the character, return status code */ return Status; } /* Nothing more to do with the exponent */ CurrentExponent = -1; } /* Check if radix character should be written */ if((Precision != 0) || (FormatProperties->Flags & PFL_PRINT_RADIX)) { /* Write the radix character */ Status = WriteWideCharacter(Context, L'.'); if(Status != STATUS_SUCCESS) { /* Failed to write the character, return status code */ return Status; } } /* Write more digits, until precision limit is reached */ for(PrecisionIndex = 0; PrecisionIndex < Precision; PrecisionIndex++) { /* Check if there is anything to write */ if(CurrentExponent > Exponent) { /* Write the next digit */ Digit = L'0'; } else if(Index < DigitCount) { /* Write the next digit */ Digit = Buffer[Index]; Index++; } else { /* Whenever reached this, write '0' character */ Digit = L'0'; } /* Write the digit */ Status = WriteWideCharacter(Context, Digit); if(Status != STATUS_SUCCESS) { /* Failed to write the character, return status code */ return Status; } /* Get next exponent character */ CurrentExponent--; } } /* Iterate through the field characters */ for(FieldIndex = 0; FieldIndex < FieldCount; FieldIndex++) { /* Fill the remaining space with spaces */ Status = WriteWideCharacter(Context, L' '); if(Status != STATUS_SUCCESS) { /* Failed to write the character, return status code */ return Status; } } /* Return success */ return STATUS_SUCCESS; } /** * Writes a wide string double value in the hexadecimal format to the destination provided by the print context. * * @param Context * Supplies a pointer to the print context structure. * * @param FormatProperties * Supplies a pointer to the print format properties structure, describing the style characteristics. * * @param Double * Supplies the double/float value to write as a wide string in a hexadecimal format. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::WideString::WriteHexDoubleValue(IN PRTL_PRINT_CONTEXT Context, IN PRTL_PRINT_FORMAT_PROPERTIES FormatProperties, IN DOUBLE Double) { LONG AbsoluteExponent, Exponent, FieldCount, Index, NumberLength; WCHAR Character, Digit, ExponentCharacter, IntegerValue; LONG Precision, PrecisionIndex, PrefixIndex, PrefixSize; ULONGLONG HalfWay, RoundingValue, Significand; WCHAR Buffer[MAX_DOUBLE_STRING_SIZE]; BOOLEAN NegativeValue; LARGE_DOUBLE Parts; WCHAR Prefix[4]; XTSTATUS Status; /* Initialize variables */ NegativeValue = FALSE; Parts.DoublePart = Double; Precision = FormatProperties->Precision; /* Check if the value is zero */ if(Double == 0.0) { AbsoluteExponent = 0; Exponent = 0; IntegerValue = L'0'; Significand = 0; /* Check if the precision is specified */ if(Precision == -1) { /* Set the precision to 0 */ Precision = 0; } /* Fill the significand hex digits buffer */ for(Index = 0; Index < DOUBLE_HEX_PRECISION; Index++) { /* Fill the buffer with zero */ Buffer[Index] = L'0'; } } else { /* Value is not zero, check if it is negative */ if((Parts.u.HighPart & (DOUBLE_SIGN_BIT >> DOUBLE_HIGH_VALUE_SHIFT)) != 0) { /* Turn the negative value into a positive one */ NegativeValue = TRUE; Parts.DoublePart *= -1; } /* Calculate exponent */ Exponent = (Parts.u.HighPart & (DOUBLE_EXPONENT_MASK >> DOUBLE_HIGH_VALUE_SHIFT)) >> (DOUBLE_EXPONENT_SHIFT - DOUBLE_HIGH_VALUE_SHIFT); Exponent -= DOUBLE_EXPONENT_BIAS; /* Get absolute exponent and check if it is negative */ AbsoluteExponent = Exponent; if(AbsoluteExponent < 0) { /* Turn the absolute exponent into a positive value */ AbsoluteExponent *= -1; } /* Calculate significand */ Significand = Parts.u.LowPart | ((ULONGLONG)(Parts.u.HighPart & DOUBLE_HIGH_VALUE_MASK) << (sizeof(ULONG) * BITS_PER_BYTE)); /* Check if the precision is specified */ IntegerValue = L'1'; if(Precision != -1) { /* Calculate the half way point and rounding value */ HalfWay = 1ULL << (DOUBLE_EXPONENT_SHIFT - 1); RoundingValue = HalfWay; if((Precision * 4) > (sizeof(ULONGLONG) * BITS_PER_BYTE)) { /* Set the rounding value to zero */ RoundingValue = 0; } else { /* Calculate the rounding value */ RoundingValue = RoundingValue >> (Precision * 4); } /* Add the rounding value to the significand */ Significand += RoundingValue; if(Significand >= (1ULL << DOUBLE_EXPONENT_SHIFT)) { /* Adjust the significand and increment the integer portion */ Significand -= (1ULL << DOUBLE_EXPONENT_SHIFT); IntegerValue++; } } /* Convert the significand into a hex string value */ for(Index = 0; Index < DOUBLE_HEX_PRECISION; Index++) { /* Get the digit value */ Digit = (Significand >> (Index * 4)) & 0xF; /* Check if the digit is less than 10 (hex A) */ if(Digit < 10) { /* Convert the digit value to a character */ Character = Digit + L'0'; } else if(FormatProperties->Flags & PFL_UPPERCASE) { /* Convert the digit value to an uppercase character */ Character = Digit + L'A' - 10; } else { /* Convert the digit value to a lowercase character */ Character = Digit + L'a' - 10; } /* Put the character in the buffer */ Buffer[DOUBLE_HEX_PRECISION - Index - 1] = Character; } /* Check if the precision is specified */ if(Precision == -1) { /* Set the precision to the number of significant digits */ Precision = DOUBLE_HEX_PRECISION; /* Find the first non-zero character */ while((Precision - 1 >= 0) && (Buffer[Precision - 1] == L'0')) { /* Decrement the precision */ Precision--; } } } /* Handle the sign character */ PrefixSize = 0; if(NegativeValue) { /* Negative value, add the '-' character */ Prefix[PrefixSize] = L'-'; PrefixSize += 1; } else if(FormatProperties->Flags & PFL_ALWAYS_PRINT_SIGN) { /* Positive value, add the '+' character */ Prefix[PrefixSize] = L'+'; PrefixSize += 1; } else if(FormatProperties->Flags & PFL_SPACE_FOR_PLUS) { /* Positive value, add the ' ' character */ Prefix[PrefixSize] = L' '; PrefixSize += 1; } /* Handle the radix characters */ Prefix[PrefixSize] = L'0'; Prefix[PrefixSize + 1] = L'x'; PrefixSize += 2; /* Get the initial number length */ NumberLength = Precision + 1; /* Check if radix is specified */ if((FormatProperties->Flags & PFL_PRINT_RADIX) || (Precision != 0)) { /* Reserve space for the radix character */ NumberLength += 1; } /* Check if uppercase characters are required */ if(FormatProperties->Flags & PFL_UPPERCASE) { /* Use uppercase 'P' character for the exponent */ ExponentCharacter = L'P'; } else { /* Use lowercase 'p' character for the exponent */ ExponentCharacter = L'p'; } /* Reserve space for exponent character, sign and digits */ NumberLength += 3; if(AbsoluteExponent > 10) { NumberLength += 1; if(AbsoluteExponent > 100) { NumberLength += 1; if(AbsoluteExponent > 1000) { NumberLength += 1; } } } /* Check if any field spacing characters are needed */ FieldCount = 0; if(NumberLength + PrefixSize < FormatProperties->FieldWidth) { /* Field width is larger than the integer part, calculate the field count */ FieldCount = FormatProperties->FieldWidth - (NumberLength + PrefixSize); } /* Check for leading zero padding and left alignment */ if(!(FormatProperties->Flags & PFL_LEFT_JUSTIFIED) || (FormatProperties->Flags & PFL_LEADING_ZEROES)) { /* Check if leading zeros are required */ if(FormatProperties->Flags & PFL_LEADING_ZEROES) { /* Write the prefix first */ Character = L'0'; PrefixIndex = 0; while(PrefixSize--) { /* Write the prefix character */ Status = WriteWideCharacter(Context, Prefix[PrefixIndex]); if(Status != STATUS_SUCCESS) { /* Failed to write character, return error code */ return Status; } /* Increment the prefix index */ PrefixIndex++; } } else { /* No leading zeros are required */ Character = L' '; } /* Write the field characters */ while(FieldCount) { /* Write the field character */ Status = WriteWideCharacter(Context, Character); if(Status != STATUS_SUCCESS) { /* Failed to write character, return error code */ return Status; } /* Decrement the field count number */ FieldCount--; } } /* Write the prefix characters */ for(PrefixIndex = 0; PrefixIndex < PrefixSize; PrefixIndex++) { /* Write the prefix character */ Status = WriteWideCharacter(Context, Prefix[PrefixIndex]); if(Status != STATUS_SUCCESS) { /* Failed to write character, return error code */ return Status; } } /* Write the integer value */ Status = WriteWideCharacter(Context, IntegerValue); if(Status != STATUS_SUCCESS) { /* Failed to write character, return error code */ return Status; } /* Check if radix character is required */ if((FormatProperties->Flags & PFL_PRINT_RADIX) || (Precision != 0)) { /* Write the radix character */ Status = WriteWideCharacter(Context, L'.'); if(Status != STATUS_SUCCESS) { /* Failed to write character, return error code */ return Status; } } /* Write the precision characters */ for(PrecisionIndex = 0; PrecisionIndex < Precision; PrecisionIndex++) { /* Check if precision index exceeds the number of significant digits */ if(PrecisionIndex >= DOUBLE_HEX_PRECISION) { /* Just write a L'0' character */ Digit = L'0'; } else { /* Write the precision character */ Digit = Buffer[PrecisionIndex]; } /* Write the precision character */ Status = WriteWideCharacter(Context, Digit); if(Status != STATUS_SUCCESS) { /* Failed to write character, return error code */ return Status; } } /* Write the exponent characters */ Status = WriteCustomValue(Context, L"%C%+d", ExponentCharacter, Exponent); if(Status != STATUS_SUCCESS) { /* Failed to write character, return error code */ return Status; } /* Write the field characters if any left */ while(FieldCount) { /* Write the field character */ Status = WriteWideCharacter(Context, L' '); if(Status != STATUS_SUCCESS) { /* Failed to write character, return error code */ return Status; } /* Decrement the field count number */ FieldCount--; } /* Return success */ return STATUS_SUCCESS; } /** * Writes a wide string integer value to the destination provided by the print context. * * @param Context * Supplies a pointer to the print context structure. * * @param FormatProperties * Supplies a pointer to the print format properties structure, describing the style characteristics. * * @param Integer * Supplies the integer value to write as a wide string. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::WideString::WriteIntegerValue(IN PRTL_PRINT_CONTEXT Context, IN PRTL_PRINT_FORMAT_PROPERTIES FormatProperties, IN ULONGLONG Integer) { LONG BufferIndex, FieldLength, IntegerLength, PrecisionLength, PrefixIndex, PrefixLength; WCHAR Buffer[MAX_INTEGER_STRING_SIZE]; ULONGLONG NextInteger, Remainder; BOOLEAN Negative; WCHAR Prefix[4]; WCHAR Character; XTSTATUS Status; /* Set default values */ IntegerLength = 0; Negative = FALSE; /* Check if this is signed integer */ if(!(FormatProperties->Flags & PFL_UNSIGNED)) { /* Check integer size and extend to signed value */ switch(FormatProperties->IntegerSize) { case sizeof(CHAR): Integer = (CHAR)Integer; break; case sizeof(SHORT): Integer = (SHORT)Integer; break; case sizeof(LONG): Integer = (LONG)Integer; break; } } /* Check if the integer value is zero */ if(Integer == 0) { /* Cannot print radix if integer is zero */ FormatProperties->Flags &= ~PFL_PRINT_RADIX; } /* Check if any of the integer value or precision is non-zero */ if(Integer != 0 || FormatProperties->Precision != 0) { /* Check if the integer is negative */ if(!(FormatProperties->Flags & PFL_UNSIGNED) && (LONGLONG)Integer < 0) { /* Mark the integer as negative and turn it positive */ Negative = TRUE; Integer *= -1; } /* Initialize the buffer */ RTL::Memory::ZeroMemory(Buffer, sizeof(Buffer)); /* Convert the integer into a reversed wide string */ do { /* Get the next digit */ NextInteger = RTL::Math::DivideUnsigned64(Integer, FormatProperties->Radix, &Remainder); /* Convert the digit into a character */ Character = (WCHAR)Remainder; if(Character > 9) { /* Check if the character should be upper case */ if(FormatProperties->Flags & PFL_UPPERCASE) { /* Get the uppercase character */ Character = Character - 10 + L'A'; } else { /* Get the lowercase character */ Character = Character - 10 + L'a'; } } else { /* Get the numeric character */ Character += L'0'; } /* Store the character in the buffer */ Buffer[IntegerLength] = Character; IntegerLength += 1; /* Get next signed digit */ Integer = NextInteger; } while(Integer > 0); /* Reverse the string representation of the integer */ ReverseWideString(Buffer, IntegerLength); } /* Handle the sign decoration */ PrefixLength = 0; if(!(FormatProperties->Flags & PFL_UNSIGNED) && Negative) { /* Signed negative value, write '-' character */ Prefix[PrefixLength] = L'-'; PrefixLength += 1; } else if(FormatProperties->Flags & PFL_ALWAYS_PRINT_SIGN) { /* Write '+' character for positive value */ Prefix[PrefixLength] = L'+'; PrefixLength += 1; } else if(FormatProperties->Flags & PFL_SPACE_FOR_PLUS) { /* Write ' ' character for positive value */ Prefix[PrefixLength] = L' '; PrefixLength += 1; } /* Handle the radix decoration */ if(FormatProperties->Flags & PFL_PRINT_RADIX) { if(FormatProperties->Radix == 8) { /* Check if leading zero is required */ if(Buffer[0] != L'0') { /* Write '0' character */ Prefix[PrefixLength] = L'0'; PrefixLength += 1; } } else if(FormatProperties->Radix == 16) { /* Write '0x' characters */ Prefix[PrefixLength] = L'0'; PrefixLength += 1; /* Write lowercase 'x' character */ Prefix[PrefixLength] = L'x'; PrefixLength += 1; } } /* Calculate the precision */ PrecisionLength = 0; if(IntegerLength < FormatProperties->Precision) { PrecisionLength = FormatProperties->Precision - IntegerLength; } /* Calculate the field length */ FieldLength = 0; if(IntegerLength + PrefixLength + PrecisionLength < FormatProperties->FieldWidth) { FieldLength = FormatProperties->FieldWidth - (IntegerLength + PrefixLength + PrecisionLength); } /* Check if leading zero padding is required and if field is left aligned */ if(!(FormatProperties->Flags & PFL_LEFT_JUSTIFIED) || (FormatProperties->Flags & PFL_LEADING_ZEROES)) { Character = L' '; if(FormatProperties->Flags & PFL_LEADING_ZEROES) { /* Write leading zero padding characters */ Character = L'0'; for(PrefixIndex = 0; PrefixIndex < PrefixLength; PrefixIndex++) { Status = WriteWideCharacter(Context, Prefix[PrefixIndex]); if(Status != STATUS_SUCCESS) { /* Failed to write character, return status code */ return Status; } } /* Clear prefix */ PrefixLength = 0; } /* Write additional field width characters */ while(FieldLength > 0) { Status = WriteWideCharacter(Context, Character); if(Status != STATUS_SUCCESS) { /* Failed to write character, return status code */ return Status; } /* Decrement field length */ FieldLength--; } } /* Write the prefix characters */ for(PrefixIndex = 0; PrefixIndex < PrefixLength; PrefixIndex++) { Status = WriteWideCharacter(Context, Prefix[PrefixIndex]); if(Status != STATUS_SUCCESS) { /* Failed to write character, return status code */ return Status; } } /* Fill the precision characters with '0' */ while(PrecisionLength > 0) { Status = WriteWideCharacter(Context, L'0'); if(Status != STATUS_SUCCESS) { /* Failed to write character, return status code */ return Status; } /* Decrement precision length */ PrecisionLength--; } /* Write the actual integer value */ for(BufferIndex = 0; BufferIndex < IntegerLength; BufferIndex++) { Status = WriteWideCharacter(Context, Buffer[BufferIndex]); if(Status != STATUS_SUCCESS) { /* Failed to write character, return status code */ return Status; } } /* Write additional field width with ' ' characters */ while(FieldLength > 0) { Status = WriteWideCharacter(Context, L' '); if(Status != STATUS_SUCCESS) { /* Failed to write character, return status code */ return Status; } /* Decrement field length */ FieldLength--; } /* Return success */ return STATUS_SUCCESS; } /** * Writes a string value to the destination provided by the print context. * * @param Context * Supplies a pointer to the print context structure. * * @param FormatProperties * Supplies a pointer to the print format properties structure, describing the style characteristics. * * @param String * Supplies the string value to write as a wide string. * * @param Character * Specifies whether the string value is expected to be a single character or not. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::WideString::WriteStringValue(PRTL_PRINT_CONTEXT Context, PRTL_PRINT_FORMAT_PROPERTIES FormatProperties, PCSTR String, SIZE_T StringLength) { WCHAR WideCharacter[2]; ULONG PaddingLength; XTSTATUS Status; /* Check for NULL string */ if(String == NULLPTR) { /* Print '(null)' instead */ String = "(null)"; StringLength = 6; } /* Check if string length exceeds precision limit */ if((FormatProperties->Precision >= 0) && (StringLength > FormatProperties->Precision)) { /* Limit string length to precision number */ StringLength = FormatProperties->Precision; } /* Calculate padding */ PaddingLength = 0; if(FormatProperties->FieldWidth > StringLength) { PaddingLength = FormatProperties->FieldWidth - StringLength; } /* Check is left side padding is required */ if(!(FormatProperties->Flags & PFL_LEFT_JUSTIFIED)) { /* Pad left */ while(PaddingLength > 0) { /* Write space */ Status = WriteWideCharacter(Context, L' '); if(Status != STATUS_SUCCESS) { /* Failed to write character, return status code */ return Status; } /* Decrement padding length */ PaddingLength--; } } /* Write string character by character */ while(StringLength) { /* Prepare wide character to write */ WideCharacter[0] = *String; WideCharacter[1] = 0; /* Write wide character */ Status = WriteWideCharacter(Context, *WideCharacter); if(Status != STATUS_SUCCESS) { /* Failed to write character, return status code */ return Status; } /* Get next character */ StringLength--; String++; } /* Pad right, if required */ while(PaddingLength > 0) { /* Write space */ Status = WriteWideCharacter(Context, L' '); if(Status != STATUS_SUCCESS) { /* Failed to write character, return status code */ return Status; } /* Decrement padding length */ PaddingLength--; } /* Return success */ return STATUS_SUCCESS; } /** * Writes a wide string value to the destination provided by the print context. * * @param Context * Supplies a pointer to the print context structure. * * @param FormatProperties * Supplies a pointer to the print format properties structure, describing the style characteristics. * * @param String * Supplies the wide string value to write. * * @param Character * Specifies whether the string value is expected to be a single character or not. * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS RTL::WideString::WriteValue(PRTL_PRINT_CONTEXT Context, PRTL_PRINT_FORMAT_PROPERTIES FormatProperties, PCWSTR String, SIZE_T StringLength) { ULONG PaddingLength; XTSTATUS Status; /* Check for NULL string */ if(String == NULLPTR) { /* Print '(null)' instead */ String = L"(null)"; StringLength = 6; } /* Check if string length exceeds precision limit */ if((FormatProperties->Precision >= 0) && (StringLength > FormatProperties->Precision)) { /* Limit string length to precision number */ StringLength = FormatProperties->Precision; } /* Calculate padding */ PaddingLength = 0; if(FormatProperties->FieldWidth > StringLength) { PaddingLength = FormatProperties->FieldWidth - StringLength; } /* Check is left side padding is required */ if(!(FormatProperties->Flags & PFL_LEFT_JUSTIFIED)) { /* Pad left */ while(PaddingLength > 0) { /* Write space */ Status = WriteWideCharacter(Context, L' '); if(Status != STATUS_SUCCESS) { /* Failed to write character, return status code */ return Status; } /* Decrement padding length */ PaddingLength--; } } /* Write string character by character */ while(StringLength != 0) { /* Write wide character */ Status = WriteWideCharacter(Context, *String); if(Status != STATUS_SUCCESS) { /* Failed to write character, return status code */ return Status; } /* Get next character */ StringLength--; String++; } /* Pad right, if required */ while(PaddingLength > 0) { /* Write space */ Status = WriteWideCharacter(Context, L' '); if(Status != STATUS_SUCCESS) { /* Failed to write character, return status code */ return Status; } /* Decrement padding length */ PaddingLength--; } /* Return success */ return STATUS_SUCCESS; } ================================================ FILE: xtoskrnl/xtoskrnl.spec ================================================ # XTOS kernel exports @ cdecl DbgPrint(wstr) @ fastcall ExAcquireRundownProtection(ptr) @ fastcall ExCompleteRundownProtection(ptr) @ fastcall ExInitializeRundownProtection(ptr) @ fastcall ExReInitializeRundownProtection(ptr) @ fastcall ExReleaseRundownProtection(ptr) @ fastcall ExWaitForRundownProtectionRelease(ptr) @ stdcall HlQueryPerformanceCounter(ptr) @ cdecl HlReadPort8(ptr) @ cdecl HlReadPort16(ptr) @ cdecl HlReadPort32(ptr) @ stdcall HlReadRegister8(ptr) @ stdcall HlReadRegister16(ptr) @ stdcall HlReadRegister32(ptr) @ stdcall HlSetClockRate(long) @ cdecl HlWritePort8(ptr long) @ cdecl HlWritePort16(ptr long) @ cdecl HlWritePort32(ptr long) @ stdcall HlWriteRegister8(ptr long) @ stdcall HlWriteRegister16(ptr long) @ stdcall HlWriteRegister32(ptr long) @ fastcall KeAcquireQueuedSpinLock(long) @ fastcall KeAcquireSpinLock(ptr) @ stdcall KeAcquireSystemResource(long ptr) @ stdcall KeCancelTimer(ptr) @ fastcall KeGetCurrentRunLevel() @ stdcall KeGetTimerState(ptr) @ stdcall KeGetSystemResource(long ptr) @ stdcall KeInitializeApc(ptr ptr long ptr ptr ptr long ptr) @ stdcall KeInitializeDpc(ptr ptr ptr) @ stdcall KeInitializeSemaphore(ptr long long) @ stdcall KeInitializeSpinLock(ptr) @ stdcall KeInitializeThreadedDpc(ptr ptr ptr) @ stdcall KeInitializeTimer(ptr long) @ fastcall KeLowerRunLevel(long) @ fastcall KeRaiseRunLevel(long) @ stdcall KeReadSemaphoreState(ptr) @ stdcall KeReleaseSemaphore(ptr long long long) @ fastcall KeReleaseQueuedSpinLock(long) @ fastcall KeReleaseSpinLock(ptr) @ stdcall KeReleaseSystemResource(ptr) @ stdcall KeSetTargetProcessorDpc(ptr long) @ stdcall KeSetTimeIncrement(long long) @ stdcall KeSetTimer(ptr long long long ptr) @ stdcall KeSignalCallDpcDone(ptr) @ stdcall KeSignalCallDpcSynchronize(ptr) @ stdcall MmAllocatePool(long long ptr) @ stdcall MmAllocatePoolWithTag(long long ptr long) @ stdcall MmFreePool(ptr) @ stdcall MmFreePoolWithTag(ptr long) @ stdcall RtlClearAllBits(ptr) @ stdcall RtlClearBit(ptr long) @ stdcall RtlClearBits(ptr long long) @ stdcall RtlClearSetBits(ptr long long) @ stdcall RtlCompareGuids(ptr ptr) @ stdcall RtlCompareMemory(ptr ptr long) @ stdcall RtlCompareString(str str long) @ stdcall RtlCompareStringInsensitive(str str long) @ stdcall RtlCompareWideString(wstr wstr long) @ stdcall RtlCompareWideStringInsensitive(wstr wstr long) @ stdcall RtlConcatenateString(str str long) @ stdcall RtlConcatenateWideString(wstr wstr long) @ stdcall RtlConvertToLargeInteger32(long) @ stdcall RtlConvertToLargeIntegerUnsigned32(long) @ stdcall RtlCopyMemory(ptr ptr long) @ stdcall RtlCopyString(ptr ptr long) @ stdcall RtlCopyWideString(ptr ptr long) @ stdcall RtlDivideLargeInteger(long long long ptr) @ stdcall RtlFindClearBits(ptr long long) @ stdcall RtlFindSetBits(ptr long long) @ stdcall RtlFindString(str str) @ stdcall RtlFindStringInsensitive(str str) @ stdcall RtlFindWideString(wstr wstr) @ stdcall RtlFindWideStringInsensitive(wstr wstr) @ stdcall RtlInitializeBitMap(ptr ptr long) @ stdcall RtlInitializeListHead(ptr) @ stdcall RtlInsertHeadList(ptr ptr) @ stdcall RtlInsertTailList(ptr ptr) @ stdcall RtlListEmpty(ptr) @ stdcall RtlListLoop(ptr) @ stdcall RtlMoveMemory(ptr ptr long) @ stdcall RtlMultiplyLargeInteger(long long long) @ stdcall RtlRemoveEntryList(ptr) @ stdcall RtlReverseString(str long) @ stdcall RtlReverseWideString(wstr long) @ stdcall RtlSameMemory(ptr ptr long) @ stdcall RtlSetAllBits(ptr) @ stdcall RtlSetBit(ptr long) @ stdcall RtlSetBits(ptr long long) @ stdcall RtlSetClearBits(ptr long long) @ stdcall RtlSetMemory(ptr long long) @ stdcall RtlStringLength(str long) @ stdcall RtlStringToWideString(wstr str long) @ stdcall RtlTestBit(ptr long) @ stdcall RtlTimeFieldsToUnixEpoch(ptr ptr) @ stdcall RtlTimeFieldsToXtEpoch(ptr ptr) @ stdcall RtlTokenizeString(str str str) @ stdcall RtlTokenizeWideString(wstr wstr wstr) @ stdcall RtlToLowerCharacter(long) @ stdcall RtlToLowerWideCharacter(long) @ stdcall RtlToUpperCharacter(long) @ stdcall RtlToUpperWideCharacter(long) @ stdcall RtlTrimLeftString(str) @ stdcall RtlTrimLeftWideString(wstr) @ stdcall RtlTrimRightString(str) @ stdcall RtlTrimRightWideString(wstr) @ stdcall RtlTrimString(str) @ stdcall RtlTrimWideString(wstr) @ stdcall RtlWideStringLength(wstr long) @ stdcall RtlZeroMemory(ptr long)