├── .editorconfig ├── .gitignore ├── CMakeLists.txt ├── CONTRIBUTE.md ├── CREDITS.md ├── LICENSE ├── README.md ├── bin ├── crypto │ └── .gitignore ├── fonts │ ├── Roboto-Medium.ttf │ └── RobotoMono-Medium.ttf ├── machines │ └── .gitignore └── pups │ └── .gitignore ├── docs ├── hardware │ ├── aeolia.md │ ├── baikal.md │ ├── belize.md │ └── liverpool.md ├── kernel │ ├── devices.md │ ├── memory.md │ └── ubios.md ├── manual-linux.md └── manual-windows.md ├── index.html ├── resources └── boot │ └── grub │ ├── boot.cfg │ ├── env-176.cfg │ ├── env-455.cfg │ ├── env-500.cfg │ └── env-common.cfg ├── src └── orbital │ ├── core.h │ ├── crypto.cpp │ ├── crypto.h │ ├── crypto_ps4.cpp │ ├── crypto_ps4.h │ ├── hardware │ ├── aeolia │ │ ├── aeolia_acpi.cpp │ │ ├── aeolia_acpi.h │ │ ├── aeolia_ahci.cpp │ │ ├── aeolia_ahci.h │ │ ├── aeolia_dmac.cpp │ │ ├── aeolia_dmac.h │ │ ├── aeolia_gbe.cpp │ │ ├── aeolia_gbe.h │ │ ├── aeolia_mem.cpp │ │ ├── aeolia_mem.h │ │ ├── aeolia_pcie.cpp │ │ ├── aeolia_pcie.h │ │ ├── aeolia_sdhci.cpp │ │ ├── aeolia_sdhci.h │ │ ├── aeolia_xhci.cpp │ │ ├── aeolia_xhci.h │ │ ├── hpet │ │ │ ├── aeolia_hpet.cpp │ │ │ └── aeolia_hpet.h │ │ ├── icc │ │ │ └── icc.h │ │ ├── msic │ │ │ ├── aeolia_msic.cpp │ │ │ └── aeolia_msic.h │ │ ├── nvs │ │ │ └── aeolia_nvs.h │ │ └── uart │ │ │ ├── aeolia_uart.cpp │ │ │ └── aeolia_uart.h │ ├── liverpool │ │ ├── acp │ │ │ └── acp.h │ │ ├── amd_regs.h │ │ ├── amd_ucode.h │ │ ├── bif │ │ │ ├── bif_4_1_d.h │ │ │ ├── bif_4_1_sh_mask.h │ │ │ └── bif_regs.h │ │ ├── dce │ │ │ ├── dce_8_0_d.h │ │ │ ├── dce_8_0_enum.h │ │ │ └── dce_8_0_sh_mask.h │ │ ├── gca │ │ │ ├── gfx.cpp │ │ │ ├── gfx.h │ │ │ ├── gfx_7_2_d.h │ │ │ ├── gfx_7_2_enum.h │ │ │ ├── gfx_7_2_sh_mask.h │ │ │ ├── pm4.cpp │ │ │ └── pm4.h │ │ ├── gmc │ │ │ ├── gmc.cpp │ │ │ ├── gmc.h │ │ │ ├── gmc_7_1_d.h │ │ │ └── gmc_7_1_sh_mask.h │ │ ├── liverpool_gc.cpp │ │ ├── liverpool_gc.h │ │ ├── liverpool_hdac.cpp │ │ ├── liverpool_hdac.h │ │ ├── liverpool_iommu.cpp │ │ ├── liverpool_iommu.h │ │ ├── liverpool_nb.cpp │ │ ├── liverpool_nb.h │ │ ├── liverpool_rc.cpp │ │ ├── liverpool_rc.h │ │ ├── liverpool_rp.cpp │ │ ├── liverpool_rp.h │ │ ├── oss │ │ │ ├── ih.cpp │ │ │ ├── ih.h │ │ │ ├── oss_2_0_d.h │ │ │ └── oss_2_0_sh_mask.h │ │ ├── sam │ │ │ ├── ccp.h │ │ │ ├── sam.cpp │ │ │ ├── sam.h │ │ │ └── sam_regs.h │ │ └── smu │ │ │ ├── smu.cpp │ │ │ ├── smu.h │ │ │ ├── smu_7_1_2_d.h │ │ │ ├── smu_7_1_2_enum.h │ │ │ └── smu_7_1_2_sh_mask.h │ ├── liverpool_pci.cpp │ ├── liverpool_pci.h │ ├── ps4.cpp │ └── ps4.h │ ├── host │ └── graphics │ │ ├── vulkan.cpp │ │ └── vulkan.h │ ├── main.cpp │ ├── offset_range.h │ ├── software │ ├── bls.cpp │ ├── bls.h │ ├── cf.cpp │ ├── cf.h │ ├── elf.cpp │ ├── elf.h │ ├── pup.cpp │ ├── pup.h │ ├── self.cpp │ └── self.h │ ├── ui.cpp │ ├── ui.h │ └── ui │ ├── charhost_imgui.cpp │ ├── charhost_imgui.h │ ├── imgui │ ├── LICENSE.txt │ ├── imgui_impl_sdl.cpp │ ├── imgui_impl_sdl.h │ ├── imgui_impl_vulkan.cpp │ ├── imgui_impl_vulkan.h │ └── widgets │ │ ├── LICENSE.txt │ │ └── imgui_memory_editor.h │ ├── tab.cpp │ ├── tab.h │ ├── tab_cpu.cpp │ ├── tab_cpu.h │ ├── tab_gpu.cpp │ ├── tab_gpu.h │ ├── tool_logs.cpp │ ├── tool_logs.h │ ├── ui_orbital.cpp │ └── ui_orbital.h ├── tests ├── Makefile ├── test_gcn_analyzer.c ├── test_gcn_disasm.c └── test_gcn_translator.cpp └── tools ├── dumper ├── .gitignore ├── Makefile ├── README.md ├── dumper.css ├── dumper.js ├── exploit │ └── 500 │ │ ├── index.html │ │ ├── kern.js │ │ └── post.js ├── index.html ├── server.py └── source │ ├── blob.c │ ├── blob.h │ ├── debug.c │ ├── debug.h │ ├── elf.h │ ├── elf32.h │ ├── elf64.h │ ├── gpu_dumper.c │ ├── gpu_dumper.h │ ├── ksdk.c │ ├── ksdk.h │ ├── ksdk.inc │ ├── ksdk_176.inc │ ├── ksdk_455.inc │ ├── ksdk_500.inc │ ├── ksdk_505.inc │ ├── ksdk_bsd.h │ ├── ksdk_gpu.h │ ├── ksdk_sbl.h │ ├── ksdk_util.h │ ├── main.c │ ├── md5.c │ ├── md5.h │ ├── pup_decrypter.c │ ├── pup_decrypter.h │ ├── self_decrypter.c │ ├── self_decrypter.h │ ├── self_mapper.c │ └── self_mapper.h ├── formats ├── gcn_orbshdr.ksy └── pci.ksy ├── gdb ├── debug-kernel.gdb └── debug-vbios.gdb ├── generate-blobs.py ├── generate-hdd.py ├── ghidra └── ioctl_probe.py ├── ida ├── analyze_kernel.py ├── analyze_user.py ├── db_syscalls.json ├── db_types.json ├── generate_sdk.py ├── generate_types.py └── get_ioctls.py ├── patch-sections-1xx.py ├── patch-sections-4xx.py ├── rai-defines.py ├── renderdoc └── orbital.cap └── slice-pup.py /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig 2 | # http://editorconfig.org 3 | 4 | root = true 5 | 6 | [**.{c,cpp,h}] 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [**.{py}] 13 | indent_style = space 14 | indent_size = 4 15 | trim_trailing_whitespace = true 16 | insert_final_newline = true 17 | 18 | [**.{html,css}] 19 | indent_style = space 20 | indent_size = 2 21 | trim_trailing_whitespace = true 22 | insert_final_newline = true 23 | 24 | [**.{js}] 25 | indent_style = space 26 | indent_size = 4 27 | trim_trailing_whitespace = true 28 | insert_final_newline = true 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries 2 | bin/*.exe 3 | bin/*.dll 4 | out/ 5 | 6 | # Dependencies 7 | vcpkg_installed 8 | 9 | # IDE 10 | .idea 11 | .vs 12 | 13 | # Objects 14 | *.a 15 | *.o 16 | 17 | # Python 18 | *.pyc 19 | 20 | # Private 21 | tools/private 22 | 23 | # TBD. 24 | CMakeSettings.json 25 | vcpkg.json 26 | externals 27 | assets/analysis/freebsd 28 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2020-2021. Alexandro Sanchez Bach. 2 | 3 | cmake_minimum_required(VERSION 3.12) 4 | 5 | # Version 6 | set(ORBITAL_VERSION_MAJOR 0) 7 | set(ORBITAL_VERSION_MINOR 1) 8 | set(ORBITAL_VERSION_PATCH 0) 9 | 10 | # Directories 11 | set(ORBITAL_DIR_ROOT ${CMAKE_CURRENT_LIST_DIR}) 12 | set(ORBITAL_DIR_CMAKE "${ORBITAL_DIR_ROOT}/cmake") 13 | set(ORBITAL_DIR_EXTERNALS "${ORBITAL_DIR_ROOT}/externals") 14 | set(ORBITAL_DIR_SOURCES "${ORBITAL_DIR_ROOT}/src") 15 | 16 | # Project 17 | project(orbital CXX) 18 | 19 | # Dependencies 20 | find_package(SDL2 REQUIRED) 21 | find_package(imgui REQUIRED) 22 | find_package(fmt CONFIG REQUIRED) 23 | find_package(RapidJSON CONFIG REQUIRED) 24 | find_package(Vulkan REQUIRED) 25 | find_package(ZLIB REQUIRED) 26 | find_library(BOTAN_LIBRARIES NAMES BOTAN2 botan2 BOTAN botan) 27 | find_library(CAPSTONE_LIBRARIES NAMES capstone_dll capstone) 28 | 29 | # Sources 30 | macro(ORBITAL_FILES_APPEND) 31 | file(GLOB FILES_APPEND CONFIGURE_DEPENDS ${ARGV}) 32 | list(APPEND ORBITAL_SOURCES ${FILES_APPEND}) 33 | endmacro() 34 | macro(ORBITAL_SOURCES_APPEND) 35 | ORBITAL_FILES_APPEND(${ARGV0}/*.h) 36 | ORBITAL_FILES_APPEND(${ARGV0}/*.cpp) 37 | endmacro() 38 | 39 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital) 40 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/analysis) 41 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/analysis/orbis) 42 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/host) 43 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/host/graphics) 44 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware) 45 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/aeolia) 46 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/aeolia/hpet) 47 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/aeolia/msic) 48 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/aeolia/uart) 49 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/liverpool) 50 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/liverpool/gca) 51 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/liverpool/gmc) 52 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/liverpool/oss) 53 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/liverpool/smu) 54 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/liverpool/sam) 55 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/software) 56 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/software/sbl) 57 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/ui) 58 | ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/ui/imgui) 59 | 60 | # Target 61 | add_executable(orbital ${ORBITAL_SOURCES}) 62 | target_include_directories(orbital PUBLIC ${ORBITAL_DIR_EXTERNALS}) 63 | target_include_directories(orbital PUBLIC ${ORBITAL_DIR_SOURCES}) 64 | target_include_directories(orbital PUBLIC ${RAPIDJSON_INCLUDE_DIRS}) 65 | target_include_directories(orbital PUBLIC ${Vulkan_INCLUDE_DIRS}) 66 | target_link_libraries(orbital PRIVATE fmt::fmt SDL2::SDL2 imgui::imgui ZLIB::ZLIB 67 | ${Vulkan_LIBRARIES} ${BOTAN_LIBRARIES} ${CAPSTONE_LIBRARIES}) 68 | if (EXISTS ${ORBITAL_DIR_EXTERNALS}/core.cmake) 69 | include(${ORBITAL_DIR_EXTERNALS}/core.cmake) 70 | else() 71 | message(FATAL_ERROR " 72 | Orbital depends on an unreleased third-party library and cannot be built without the required `core.cmake` script. 73 | Functionality related to PS4 emulation/introspection is open-sourced *only* as documentation for fellow developers and hackers. 74 | To build Orbital, wait for the upcoming release of `core.cmake` or reimplement one yourself that includes/links QEMU instead. 75 | Please do NOT ask for help/support related to `core.cmake` issues.") 76 | endif() 77 | 78 | # Properties 79 | set_target_properties(orbital PROPERTIES CXX_STANDARD 20) 80 | set_target_properties(orbital PROPERTIES CXX_STANDARD_REQUIRED ON) 81 | set_target_properties(orbital PROPERTIES POSITION_INDEPENDENT_CODE 1) 82 | -------------------------------------------------------------------------------- /CREDITS.md: -------------------------------------------------------------------------------- 1 | # Credits 2 | 3 | ## Author 4 | 5 | Original developer of this project. 6 | 7 | - `Alexandro Sanchez ` 8 | 9 | 10 | ## Maintainers 11 | 12 | Current lead developers and responsible of reviews and maintenance. 13 | 14 | - `Alexandro Sanchez ` 15 | 16 | 17 | ## Developers 18 | 19 | Current and former regular developers. 20 | 21 | - `Alexandro Sanchez ` 22 | - `Nick Renieris ` 23 | - `Jake Arveson ` 24 | 25 | 26 | ## Contributors 27 | 28 | People who have occasionally contributed to this project. 29 | 30 | - `Mason Lee Back ` 31 | - `Andrey (@jfhs) ` 32 | - `Zion Nimchuk ` 33 | 34 | 35 | ## Supporters 36 | 37 | People who provided non-technical support: donations, hardware, etc. 38 | 39 | (TBD.) 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Alexandro Sanchez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Orbital 2 | ======= 3 | 4 | Virtualization-based PlayStation 4 emulator. 5 | 6 | ## Status 7 | 8 | The current state of Orbital at booting decrypted kernels can be followed in the issue tracker: both [PS4 4.55](https://github.com/AlexAltea/orbital/issues/3) and [PS4 5.00](https://github.com/AlexAltea/orbital/issues/4) have been tested. You can also get occasional updates and news via [Twitter](https://twitter.com/AlexAltea). 9 | 10 | Future plans for the emulator can be found at the [Roadmap](https://github.com/AlexAltea/orbital/wiki/Roadmap) page. 11 | 12 | ## FAQ 13 | 14 | > Where can I get Orbital? 15 | 16 | **This project is not ready for end users.** No binaries are provided, so you must build each of the three components (BIOS, GRUB, QEMU) yourself. Furthermore, configuring the emulator to do something will be hard, as you will need to extract your own console keys. More information and guides on this matter will be available in the future. 17 | 18 | ## Requirements 19 | 20 | * __System__: Windows (7+), Linux (4.4+), macOS (10.10+). 21 | * __Processor__: x86-64 CPU with AVX/BMI1 and virtualization extensions. 22 | * __Memory__: 12 GB RAM. 23 | * __Graphics__: GPU with software support for Vulkan 1.0+. 24 | 25 | ## Acknowledgements 26 | 27 | Thanks to all people who have directly or indirectly helped in making this possible. In alphabetical order: *flatz, idc, m0rph3us1987, masterzorag, proxima, wildcard, x41, zecoxao, zer0xff, z80*. Also many anonymous folks and others who might have slipped my mind. You know who you are! 28 | -------------------------------------------------------------------------------- /bin/crypto/.gitignore: -------------------------------------------------------------------------------- 1 | # Files 2 | *.json 3 | -------------------------------------------------------------------------------- /bin/fonts/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexAltea/orbital/cc408367da6a6ebbf5ac1ac559fefeadc73b2831/bin/fonts/Roboto-Medium.ttf -------------------------------------------------------------------------------- /bin/fonts/RobotoMono-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexAltea/orbital/cc408367da6a6ebbf5ac1ac559fefeadc73b2831/bin/fonts/RobotoMono-Medium.ttf -------------------------------------------------------------------------------- /bin/machines/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything... 2 | * 3 | 4 | # Except this file 5 | !.gitignore 6 | -------------------------------------------------------------------------------- /bin/pups/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything 2 | * 3 | 4 | # Except this file 5 | !.gitignore 6 | -------------------------------------------------------------------------------- /docs/hardware/aeolia.md: -------------------------------------------------------------------------------- 1 | Aeolia 2 | ====== 3 | 4 | - 104D:908F Aeolia ACPI 5 | - 104D:909E Aeolia GBE controller 6 | - 104D:909F Aeolia AHCI 7 | - 104D:90A0 Aeolia SDHCI 8 | - 104D:90A1 Aeolia PCI Express glue 9 | - 104D:90A2 Aeolia DMA controller 10 | - 104D:90A3 Aeolia Memory (DDR3/SPM) 11 | - 104D:90A4 Aeolia XHCI USB 3.0 controller 12 | -------------------------------------------------------------------------------- /docs/hardware/baikal.md: -------------------------------------------------------------------------------- 1 | Baikal 2 | ====== 3 | 4 | - 104D:90D7 Baikal ACPI 5 | - 104D:90D8 Baikal GBE controller 6 | - 104D:90D9 Baikal AHCI 7 | - 104D:90DA Baikal SDHCI 8 | - 104D:90DB Baikal PCI Express glue 9 | - 104D:90DC Baikal DMA controller 10 | - 104D:90DD Baikal Memory (DDR3/SPM) 11 | - 104D:90DE Baikal XHCI USB 3.0 controller 12 | -------------------------------------------------------------------------------- /docs/hardware/belize.md: -------------------------------------------------------------------------------- 1 | Belize 2 | ====== 3 | 4 | - 104D:90C8 Belize ACPI 5 | - 104D:90C9 Belize GBE controller 6 | - 104D:90CA Belize AHCI 7 | - 104D:90CB Belize SDHCI 8 | - 104D:90CC Belize PCI Express glue 9 | - 104D:90CD Belize DMA controller 10 | - 104D:90CE Belize Memory (DDR3/SPM) 11 | - 104D:90CF Belize XHCI USB 3.0 controller 12 | -------------------------------------------------------------------------------- /docs/kernel/memory.md: -------------------------------------------------------------------------------- 1 | ## Memory 2 | 3 | ### ??? 4 | 5 | Base: 6 | 7 | - `0xFFFFFE0000000000`: <= 1.76 (?) 8 | - `0xFFFF800000000000`: >= 4.55 (?) 9 | 10 | Offset | Size | Description 11 | ------------:|---------:|------------ 12 | `0x9B000` | `0x1000` | Boot 13 | `0xD0340000` | `0x1000` | UART 14 | `0xD0341000` | `0x1000` | UART (devtype 0x63) 15 | 16 | ### Kernel 17 | 18 | -------------------------------------------------------------------------------- /docs/kernel/ubios.md: -------------------------------------------------------------------------------- 1 | # UBIOS 2 | 3 | Mapped into [0x680000,0x6FFFFF] which is aliasedsize at the end of 32-bit physical address space. 4 | The x86 CPU init/reset state set CS:IP := 0xFFFFFFF0, matching the 80010002 entry point (0x6FFFF0) thanks to the alias. 5 | 6 | ## AGESA 7 | 8 | One of three available images will be loaded at 0x680000: 9 | 10 | - GladiusBDK 11 | - ClaytonBDK 12 | - ThebePBDK 13 | 14 | ## KASLR 15 | 16 | The 20-byte buffer at 0x600160 is memcpy'd to a zero-initialized 80-byte SHA1 block, and a single SHA1 transform (80 rounds) is applied. 17 | The first word (4 bytes) of the resulting digest plays a role in different parts of the kernel loading as a source of pseudo-randomness. 18 | Specifically, the first word & 0x7FFF becomes shifted by 14 bits becomes the KASLR offset applied to the kernel base. 19 | 20 | One can easily defeat KASLR by finding a preimage that results in the first 2 bytes (thanks little-endian!) being 0x00. 21 | -------------------------------------------------------------------------------- /docs/manual-linux.md: -------------------------------------------------------------------------------- 1 | # Manual for Linux 2 | 3 | ## Building 4 | 5 | Building Orbital has following absolute prerequisites: 6 | 7 | * GCC/Clang 9.0+. 8 | * [CMake 3.12](https://cmake.org/)+. 9 | 10 | Additionally, install the following libraries: 11 | 12 | * [`glslang`](https://github.com/KhronosGroup/glslang). 13 | * [`imgui`](https://github.com/ocornut/imgui/). 14 | * [`libzip`](https://libzip.org/). 15 | * [`sdl2`](https://www.libsdl.org/). 16 | * [`vulkan`](https://vulkan.lunarg.com/sdk/). 17 | * [`zlib`](https://zlib.net/). 18 | 19 | Although you might download them all and forward them to CMake via the 20 | appropriate variables (e.g. `SDL2_DIR`, `IMGUI_DIR`, etc.), we recommend 21 | to manage dependencies via [vcpkg](https://github.com/Microsoft/vcpkg). 22 | With *vcpkg*, dependencies declared in the [`vcpkg.json`](/vcpkg.json) 23 | manifest file will be automatically built and installed. 24 | 25 | Alternatively, you can install these dependencies with your package manager: 26 | * Ubuntu: 27 | ```bash 28 | sudo apt install -qq glslang-dev libsdl2-dev libvulkan-dev libzip-dev zlib1g-dev 29 | ``` 30 | * Arch Linux: 31 | ```bash 32 | sudo pacman -S glslang libzip sdl2 vulkan-validation-layers vulkan-icd-loader vulkan-headers zlib 33 | ``` 34 | 35 | Then, clone this repository: 36 | 37 | ```bash 38 | git clone --depth 1 https://github.com/AlexAltea/orbital 39 | cd orbital 40 | ``` 41 | 42 | And build Orbital with: 43 | 44 | ```bash 45 | cmake -B build . 46 | cmake --build build 47 | ``` 48 | 49 | 50 | ## Installing 51 | 52 | 1. Build *Orbital* as described previously. 53 | 54 | 2. Make sure that your system supports Intel VTX or AMD-V, and that these features are enabled. 55 | 56 | 3. TBD. (You need to legally own a PS4 console for this step). 57 | 58 | 4. Place this file in the `bin/crypto` folder. 59 | 60 | 61 | ## Running 62 | 63 | Go to the `bin` folder and run *Orbital* with the command: 64 | 65 | ```bash 66 | ./orbital 67 | ``` 68 | 69 | On your first run: you will be asked to create a new virtual PS4 console, and optionally, 70 | to specify a recovery PUP to boot from. 71 | -------------------------------------------------------------------------------- /docs/manual-windows.md: -------------------------------------------------------------------------------- 1 | # Manual for Windows 2 | 3 | ## Building 4 | 5 | Building Orbital has following absolute prerequisites: 6 | 7 | * [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/)+. 8 | * [CMake 3.12](https://cmake.org/)+. 9 | 10 | Additionally, install the following libraries: 11 | 12 | * [`glslang`](https://github.com/KhronosGroup/glslang). 13 | * [`imgui`](https://github.com/ocornut/imgui/). 14 | * [`libzip`](https://libzip.org/). 15 | * [`sdl2`](https://www.libsdl.org/). 16 | * [`vulkan`](https://vulkan.lunarg.com/sdk/). 17 | * [`zlib`](https://zlib.net/). 18 | 19 | Although you might download them all and forward them to CMake via the 20 | appropriate variables (e.g. `SDL2_DIR`, `IMGUI_DIR`, etc.), we recommend 21 | to manage dependencies via [vcpkg](https://github.com/Microsoft/vcpkg). 22 | With *vcpkg*, dependencies declared in the [`vcpkg.json`](/vcpkg.json) 23 | manifest file will be automatically built and installed. 24 | 25 | Then, clone this repository: 26 | 27 | ```bash 28 | git clone --depth 1 https://github.com/AlexAltea/orbital 29 | cd orbital 30 | ``` 31 | 32 | And build Orbital with: 33 | 34 | ```bash 35 | cmake -B build . 36 | cmake --build build 37 | ``` 38 | 39 | 40 | ## Installing 41 | 42 | 1. Build *Orbital* as described previously. 43 | 44 | 2. Make sure that your system supports Intel VTX or AMD-V, and that these features are enabled. 45 | 46 | 3. TBD. (You need to legally own a PS4 console for this step). 47 | 48 | 4. Place this file in the `bin/crypto` folder. 49 | 50 | 51 | ## Running 52 | 53 | Go to the `bin` folder and run *Orbital* with the command: 54 | 55 | ```bash 56 | $ ./orbital.exe 57 | ``` 58 | 59 | On your first run: you will be asked to create a new virtual PS4 console, and optionally, 60 | to specify a recovery PUP to boot from. 61 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Orbital 7 | 46 | 47 | 48 | 49 |
50 |
51 |

Orbital

52 |

Coming 2049

53 |
54 | GitHub - 55 | Discord 56 |
57 | 58 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /resources/boot/grub/boot.cfg: -------------------------------------------------------------------------------- 1 | korbis (sflash)/orbisys-500 2 | source (memdisk)/boot/grub/env-500.cfg 3 | korbis_loadenv (memdisk)/boot/grub/env-common.cfg 4 | boot 5 | -------------------------------------------------------------------------------- /resources/boot/grub/env-176.cfg: -------------------------------------------------------------------------------- 1 | source (memdisk)/boot/grub/env-common.cfg 2 | 3 | ### OPTIONAL 4 | 5 | # Enable bootverbose flag 6 | # ======================= 7 | # This flags is set whenever `boothowto` has the flag 0x800 enabled. 8 | # Since `boothowto` is hardcoded inside `hammer_time`, we patch the 9 | # corresponding `mov` instruction. 10 | write_dword 0x260443C 0x800 0x800 11 | 12 | ### REQUIRED 13 | 14 | # Enable cn_mute flag 15 | # =================== 16 | # During initialization in `hammer_time`, the function `pmap_bootstrap` is 17 | # called which will always call `printf` (and thus `cnputc`) on success. 18 | # This requires the `cn_devlist` data structure to be filled by `cninit`. 19 | # However, `cninit` is not called until after `pmap_bootstrap` has returned. 20 | # To prevent this issue, we manually enable the `cn_mute` flag, which will be 21 | # set or unset during `cninit` based on boot flags. 22 | # Values: 23 | # - 0x0 Disable cn_mute 24 | # - 0x1 Enable cn_mute 25 | write_dword 0x32B3A98 0x1 26 | 27 | # Fix cn_devlist 28 | # ============== 29 | # This linked list should point back to its head, but for some 30 | # inexplicable reason it points to cn_devtab, causing problems. 31 | # during cnremove / cnadd operations. 32 | write_dword 0x3235510 0x0 33 | write_dword 0x3235514 0x0 34 | write_dword 0x3235518 0x83235510 35 | write_dword 0x323551C 0xFFFFFFFF 36 | -------------------------------------------------------------------------------- /resources/boot/grub/env-455.cfg: -------------------------------------------------------------------------------- 1 | source (memdisk)/boot/grub/env-common.cfg 2 | 3 | ### OPTIONAL 4 | 5 | # Enable bootverbose flag 6 | # ======================= 7 | # This flags is set whenever `boothowto` has the flag 0x800 enabled. 8 | # Since `boothowto` is hardcoded inside `hammer_time`, we patch the 9 | # corresponding `mov` instruction. 10 | write_dword 0x2481466 0x800 0x800 11 | 12 | ### HACKS 13 | 14 | # Disable VBIOS code 15 | write_byte 0x269FF40 0xC3 16 | write_byte 0x26A0210 0xC3 17 | 18 | # Disable `sflash_hrt_usleep` 19 | # ========================== 20 | # This prevents the kernel from waiting for an event that never occurs, 21 | # presumably caused by a missing feature in the implementation of the sflash interface 22 | # inside Aeolia's PCIe glue device (missing/wrong interrupt fired). 23 | #write_byte TODO 0xC3 24 | -------------------------------------------------------------------------------- /resources/boot/grub/env-500.cfg: -------------------------------------------------------------------------------- 1 | source (memdisk)/boot/grub/env-common.cfg 2 | 3 | ### OPTIONAL 4 | 5 | # Enable bootverbose flag 6 | # ======================= 7 | # This flags is set whenever `boothowto` has the flag 0x800 enabled. 8 | # Since `boothowto` is hardcoded inside `hammer_time`, we patch the 9 | # corresponding `mov` instruction. 10 | write_dword 0x243341E 0x800 0x800 11 | 12 | # Configure gbase trace level 13 | # =========================== 14 | # The GPU driver functions, gbase_*, ocassionally query the `g_tracelevel` 15 | # variable to conditionally print debug information based on the current 16 | # tracing level. This is zero-initialized by default. 17 | write_dword 0x46ACDD0 0x00 18 | 19 | # Configure GEOM trace level 20 | # ========================== 21 | # The GEOM driver functions, g_*, ocassionally query the `g_debugflags` 22 | # variable to conditionally print debug information based on the current 23 | # tracing level in g_trace. This is zero-initialized by default. 24 | # This is a flags value where each bit indicates a debug level, which 25 | # seem just { 0x1, 0x2, 0x4 }. Hence 0x7 should enable all output. 26 | write_dword 0x4569700 0x00 27 | 28 | # Configure XHCI trace level 29 | # ========================== 30 | # The XHCI driver functions, xhci_*, ocassionally query the `xhcidebug` 31 | # variable to conditionally print debug information based on the current 32 | # tracing level in `xhcidebug`. This is zero-initialized by default. 33 | # The levels go from 0x1 to 0x10 and are checked for higher-equal value. 34 | write_dword 0x4581840 0x00 35 | 36 | # Configure USB trace level 37 | # ========================= 38 | # The USB driver functions, {hid,usb,usbd}_*, ocassionally query the `usb*_debug` 39 | # variables to conditionally print debug information based on the current tracing 40 | # level stired in them. These are zero-initialized by default. 41 | # These two variables are, in order: 42 | # - usb_debug: Levels 0x1-to-0xB and checked for higher-equal value. 43 | # - usb_ctrl_debug: Levels 0x1-to-0x1 and checked for higher-equal value. 44 | # - usb_proc_debug: Levels 0x1-to-0x1 and checked for higher-equal value. 45 | write_dword 0x3CEB480 0x00 46 | write_dword 0x457E600 0x00 47 | write_dword 0x3CCE828 0x00 48 | 49 | ### HACKS 50 | 51 | # Fix `aeolia_emctimer_read` 52 | # ========================= 53 | # The kernel performs multiple reads on the Aeolia EMC timer (clocked at 32.768 KHz), 54 | # until two consecutive reads yield the same timestamp. Unfortunately, while doing 55 | # virtualization, the 30-microsecond window is to small for this to happen, so we 56 | # patch the checks away. 57 | # One explanation for the need of making identical consecutive reads in the drivers, 58 | # is that the underlying timer is connected via an 8-bit bus, so reads in real consoles 59 | # might yield partially updated values. 60 | write_byte 0x25B4CA6 0x90 61 | write_byte 0x25B4CA7 0x90 62 | -------------------------------------------------------------------------------- /resources/boot/grub/env-common.cfg: -------------------------------------------------------------------------------- 1 | ### Environment 2 | hw.memtest.tests=0 3 | hw.clflush_disable=1 4 | #hw.acpi.verbose=1 5 | #hw.usb.xhci.debug=1 6 | #kern.init_safe_mode=0 7 | #kern.geom.label.debug=2 8 | #kern.geom.debugflags=255 9 | #kern.maxusers= 10 | #kern.maxproc= 11 | #kern.ncallout= 12 | #kern.ipc.maxpipekva= 13 | 14 | # HACK: 15 | # During TSC synchronization tests, FreeBSD/Orbis checks whether whether 16 | # the TSCs in all CPUs are sychronized. It does so by repeatedly querying 17 | # via `smp_rendezvous` three functions that store the current TSC. this 18 | # Since these three functions are separated by SMP barriers, the kernel just 19 | # checks that all stages contain values larger than the previous stage. 20 | # This assumption breaks on some hypervisors, e.g. HAXM, which is why the 21 | # test is skipped if `vm_guest` is enabled. We enable it by specifying 22 | # a `smbios.bios.vendor` value matching an emulator, e.g. "QEMU". 23 | # As a side-effect of removing this test, we reduce boot time 10 seconds. 24 | # 25 | # TODO: In the future, we should try to fix that directly at HAXM-level. 26 | # NOTE: This hack exposes a bug in the GC drivers. When `vm_guest` is enabled, 27 | # the kernel changes the default hz from 1000 to 100. The `gc_open` 28 | # function calls `pause` with a timeout value of 0 if `hz` is 100. 29 | # We fix that by hardcoding the default value of `hz` in non-guests. 30 | smbios.bios.vendor=QEMU 31 | kern.hz=1000 32 | 33 | ### Loader 34 | 35 | # Enable debug 36 | # ==================== 37 | # Used by `sceSblRcMgrIsAllowSLDebugger` 38 | write_byte 0x9B496 0x4 0x4 39 | write_byte 0x9B4B9 0x2 0x2 40 | 41 | 42 | ### IDPS 43 | 44 | # Unknown 45 | # ==================== 46 | write_dword 0x9B498 0x0 47 | 48 | # Product Code: Unknown 49 | # ==================== 50 | # Used by `sceSblAIMgrIs*` functions. Seems to be always 0x01. 51 | write_byte 0x9B49C 0x01 52 | 53 | # Product Code: Target ID 54 | # ======================= 55 | # These values are stored in big-endian format. 56 | # Used by `sceSblAIMgrIs*` functions. 57 | # Values: 58 | # - 0x80 Diag (TEST) 59 | # - 0x81 DevKit (TOOL) 60 | # - 0x82 TestKit (DEX) 61 | # - 0x83 Retail (CEX:J1) 62 | # - 0x84 Retail (CEX:UC2) 63 | # - 0x85 Retail (CEX:CEL) 64 | # - 0x86 Retail (CEX:KR2) 65 | # - 0x87 Retail (CEX:CEK) 66 | # - 0x88 Retail (CEX:MX2) 67 | # - 0x89 Retail (CEX:AU3) 68 | # - 0x8A Retail (CEX:E12) 69 | # - 0x8B Retail (CEX:TW1) 70 | # - 0x8C Retail (CEX:RU3) 71 | # - 0x8D Retail (CEX:CN9) 72 | # - 0x8E Retail (CEX:HK5) 73 | # - 0x8F Retail (CEX:BR2) 74 | # - 0x90 Retail (CEX:?) 75 | # - 0x91 Retail (CEX:?) 76 | # - 0xA0 ??? 77 | write_byte 0x9B49D 0x82 78 | 79 | # Product Subcode 80 | # =============== 81 | write_byte 0x9B49E 0x00 82 | write_byte 0x9B49F 0x00 83 | 84 | # Chasis Check 85 | # ============ 86 | write_byte 0x9B4A0 0x00 87 | write_byte 0x9B4A1 0x00 88 | 89 | # Identifier 90 | # ========== 91 | write_byte 0x9B4A0 0x11 92 | write_byte 0x9B4A1 0x22 93 | write_byte 0x9B4A2 0x33 94 | write_byte 0x9B4A3 0x44 95 | write_byte 0x9B4A4 0x55 96 | write_byte 0x9B4A5 0x66 97 | 98 | 99 | ### ??? (Copied straight from 5.01 dump) 100 | 101 | # TSC frequency 102 | # ============= 103 | # This represents the frequency of TSC ticks in the CPU divided by 996250. 104 | # The value for the PS4 CPU is 0x640. 105 | # TODO: Might require to be configured by the emulator to match the 106 | # host CPU TSC frequency to prevent timing issues during virtualization. 107 | write_word 0x9B6BC 0x640 108 | 109 | # Unknown 110 | write_byte 0x9B6BF 0xFF 111 | 112 | # Unknown 113 | write_dword 0x9B6C4 0x0 114 | write_dword 0x9B6C8 0x0 115 | 116 | # ... 117 | 118 | # Unknown 119 | write_byte 0x9B6DD 0xFF 120 | 121 | # Unknown 122 | write_dword 0x9BB44 0xFFFFFFFF 123 | 124 | # Unknown 125 | write_dword 0x9BB48 0x00000001 126 | 127 | 128 | ### Starsha 129 | # This region is 0x400 bytes in size 130 | write_byte 0x9B744 0x00 131 | -------------------------------------------------------------------------------- /src/orbital/core.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Core. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #if __has_include("../externals/core.h") 14 | #include <../externals/core.h> 15 | #else 16 | #error "Orbital depends on an unreleased third-party library and cannot be built without the required header. \ 17 | Functionality related to PS4 emulation/introspection is open-sourced *only* as documentation for fellow developers and hackers. \ 18 | To build Orbital, wait for the upcoming release of or reimplement your own by forwarding function calls to QEMU. \ 19 | Please do NOT ask for help/support related to issues." 20 | #endif 21 | -------------------------------------------------------------------------------- /src/orbital/crypto.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Cryptography. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "crypto.h" 12 | 13 | #include 14 | 15 | U64 CryptoStream::read(U64 size, void* buffer) { 16 | return 0; 17 | } 18 | 19 | U64 CryptoStream::write(U64 size, const void* buffer) { 20 | return 0; 21 | } 22 | 23 | void CryptoStream::seek(U64 offset, StreamSeek mode) { 24 | s.seek(offset, mode); 25 | } 26 | 27 | U64 CryptoStream::tell() const { 28 | return s.tell(); 29 | } 30 | 31 | void Crypto::decrypt(void* buf, size_t len, Key key) { 32 | Crypto::decrypt(buf, len, buf, len, key); 33 | } 34 | 35 | void Crypto::decrypt(const void* input_buf, size_t input_len, 36 | void* output_buf, size_t output_len, Key key) { 37 | const char* algo; 38 | switch (key.type) { 39 | case Key::AES_128_EBC: 40 | algo = "AES-128/EBC"; 41 | break; 42 | case Key::AES_128_CBC: 43 | algo = "AES-128/CBC/CTS"; 44 | break; 45 | default: 46 | throw std::invalid_argument("Unrecognized key type"); 47 | } 48 | auto cipher = Botan::get_cipher(algo, key.key, key.iv, Botan::Cipher_Dir::DECRYPTION); 49 | Botan::Pipe pipe(cipher); 50 | pipe.start_msg(); 51 | pipe.write((const uint8_t*)input_buf, input_len); 52 | pipe.end_msg(); 53 | pipe.read((uint8_t*)output_buf, output_len); 54 | } 55 | 56 | Buffer Crypto::decrypt(const Buffer& buffer, Key key) { 57 | Buffer output(buffer.size()); 58 | decrypt(buffer.data(), buffer.size(), output.data(), output.size(), key); 59 | return output; 60 | } 61 | 62 | CryptoStream Crypto::decrypt(Stream& s, Key key) { 63 | return CryptoStream(s, key); 64 | } 65 | -------------------------------------------------------------------------------- /src/orbital/crypto_ps4.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * PS4 cryptography. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "crypto.h" 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | static Crypto g_ps4Crypto; 20 | 21 | static Key parseAesKey(Key::Type type, const rapidjson::Value& value) { 22 | auto key = value["aes_key"].GetString(); 23 | auto iv = value["aes_iv"].GetString(); 24 | return Key(type, key, iv); 25 | } 26 | 27 | const Crypto& ps4Crypto() { 28 | if (g_ps4Crypto.size() > 0) { 29 | return g_ps4Crypto; 30 | } 31 | 32 | // Parse keys from hardcoded file 33 | std::ifstream ifs("crypto/keys.json"); 34 | rapidjson::IStreamWrapper isw(ifs); 35 | rapidjson::Document document; 36 | document.ParseStream(isw); 37 | 38 | // Add individual keys 39 | g_ps4Crypto.add("pup.hdr", 40 | parseAesKey(Key::AES_128_CBC, document["pup"]["hdr"])); 41 | g_ps4Crypto.add("pup.root_key", 42 | parseAesKey(Key::AES_128_CBC, document["pup"]["root_key"])); 43 | 44 | for (const auto& m : document["self"]["80010002"].GetObject()) { 45 | std::string name = "self.80010002."; 46 | g_ps4Crypto.add(name + m.name.GetString(), parseAesKey(Key::AES_128_CBC, m.value)); 47 | } 48 | 49 | return g_ps4Crypto; 50 | } 51 | -------------------------------------------------------------------------------- /src/orbital/crypto_ps4.h: -------------------------------------------------------------------------------- 1 | /** 2 | * PS4 cryptography. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | /** 16 | * Returns the global Crypto object that stores/uses PS4 keys. 17 | * Ideally, keys should be hardcoded in the hardware/software emulators. 18 | * However for legal reasons we are not allowed to ship cryptographic keys, 19 | * hence this annoying layer of abstraction. 20 | */ 21 | const Crypto& ps4Crypto(); 22 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_acpi.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia ACPI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "aeolia_acpi.h" 12 | 13 | constexpr U32 AEOLIA_V1 = 0x00000100; 14 | constexpr U32 AEOLIA_V2 = 0x00000200; 15 | constexpr U32 AEOLIA_V3 = 0x00000300; 16 | constexpr U32 AEOLIA_V4 = 0x01000100; 17 | constexpr U32 AEOLIA_V5 = 0x01000200; 18 | constexpr U32 AEOLIA_V6 = 0x02000100; 19 | constexpr U32 AEOLIA_V7 = 0x10000100; 20 | constexpr U32 AEOLIA_V8 = 0x10000200; 21 | constexpr U32 AEOLIA_V9 = 0x10000201; 22 | 23 | AeoliaACPIDevice::AeoliaACPIDevice(PCIeBus* bus, const AeoliaACPIDeviceConfig& config) 24 | : PCIeDevice(bus, config) { 25 | // Define BARs 26 | mem = new MemorySpace(this, 0x2000000, { 27 | static_cast(&AeoliaACPIDevice::mem_read), 28 | static_cast(&AeoliaACPIDevice::mem_write), 29 | }); 30 | io = new MemorySpace(this, 0x100, { 31 | static_cast(&AeoliaACPIDevice::io_read), 32 | static_cast(&AeoliaACPIDevice::io_write), 33 | }); 34 | 35 | // Register BARs 36 | register_bar(0, PCI_BASE_ADDRESS_SPACE_MEM, mem); 37 | register_bar(2, PCI_BASE_ADDRESS_SPACE_IO, io); 38 | 39 | reset(); 40 | } 41 | 42 | AeoliaACPIDevice::~AeoliaACPIDevice() { 43 | delete mem; 44 | delete io; 45 | } 46 | 47 | void AeoliaACPIDevice::reset() { 48 | // PCI Configuration Space 49 | auto& header = config_header(); 50 | header.command = PCI_COMMAND_IO | PCI_COMMAND_MEMORY; // TODO: Is this needed? 51 | header.header_type |= PCI_HEADER_TYPE_MULTI_FUNCTION; 52 | header.class_prog = 0x00; 53 | msi_enable(1, true); 54 | 55 | // Add PCIe capability 56 | // TODO: Refactor this code 57 | const auto cap_off = add_capability(PCI_CAP_ID_EXP, 0x14 /* V1 */, 0x70); 58 | (U16&)config_data[cap_off + 2 /*PCI_EXP_FLAGS*/ ] = 0x0001; 59 | (U32&)config_data[cap_off + 4 /*PCI_EXP_DEVCAP*/] = 0; 60 | (U16&)config_data[cap_off + 8 /*PCI_EXP_DEVCTL*/] = 0; 61 | (U16&)config_data[cap_off + 10 /*PCI_EXP_DEVSTA*/] = 0; 62 | (U32&)config_data[cap_off + 12 /*PCI_EXP_LNKCAP*/] = 0; 63 | (U16&)config_data[cap_off + 16 /*PCI_EXP_LNKCTL*/] = 0; 64 | (U16&)config_data[cap_off + 18 /*PCI_EXP_LNKSTA*/] = 0; 65 | 66 | constexpr U32 aeolia_version = AEOLIA_V3; 67 | (U32&)config_data[0x064] = aeolia_version; // HACK: We don't support MSR-based PCIe config space access, so 0x164 becomes 0x64. 68 | (U32&)config_data[0x164] = aeolia_version; 69 | } 70 | 71 | U64 AeoliaACPIDevice::mem_read(U64 addr, U64 size) { 72 | assert_always("Unimplemented"); 73 | return 0; 74 | } 75 | 76 | void AeoliaACPIDevice::mem_write(U64 addr, U64 value, U64 size) { 77 | assert_always("Unimplemented"); 78 | } 79 | 80 | U64 AeoliaACPIDevice::io_read(U64 addr, U64 size) { 81 | //assert_always("Unimplemented"); 82 | return 0; 83 | } 84 | 85 | void AeoliaACPIDevice::io_write(U64 addr, U64 value, U64 size) { 86 | //assert_always("Unimplemented"); 87 | } 88 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_acpi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia ACPI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | enum { 16 | AEOLIA_ACPI_DEV = 0x14, 17 | AEOLIA_ACPI_FNC = 0x0, 18 | }; 19 | 20 | constexpr auto AEOLIA_ACPI_VID = static_cast(0x104D); 21 | constexpr auto AEOLIA_ACPI_DID = static_cast(0x908F); 22 | 23 | struct AeoliaACPIDeviceConfig : PCIeDeviceConfig { 24 | AeoliaACPIDeviceConfig(PCI_DF df = PCI_DF(AEOLIA_ACPI_DEV, AEOLIA_ACPI_FNC)) 25 | : PCIeDeviceConfig(df, AEOLIA_ACPI_VID, AEOLIA_ACPI_DID, 0x0, PCI_CLASS_SYSTEM_OTHER) { 26 | } 27 | }; 28 | 29 | class AeoliaACPIDevice final : public PCIeDevice { 30 | public: 31 | AeoliaACPIDevice(PCIeBus* bus, const AeoliaACPIDeviceConfig& config = {}); 32 | ~AeoliaACPIDevice(); 33 | 34 | // Device interface 35 | void reset() override; 36 | 37 | private: 38 | MemorySpace* mem; 39 | MemorySpace* io; 40 | 41 | U64 mem_read(U64 addr, U64 size); 42 | void mem_write(U64 addr, U64 value, U64 size); 43 | 44 | U64 io_read(U64 addr, U64 size); 45 | void io_write(U64 addr, U64 value, U64 size); 46 | }; 47 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_ahci.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia AHCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "aeolia_ahci.h" 12 | 13 | constexpr U32 AEOLIA_AHCI_BAR_IDP = 4; 14 | constexpr U32 AEOLIA_AHCI_BAR_MEM = 5; 15 | 16 | AeoliaAHCIDevice::AeoliaAHCIDevice(PCIeBus* bus, const AeoliaAHCIDeviceConfig& config) 17 | : PCIeDevice(bus, config) { 18 | 19 | // Create AHCI device 20 | Interrupt* irq = allocate_irq(); 21 | ahci = new AHCIDevice(this, _machine->mem(), irq); 22 | 23 | // Register BARs 24 | register_bar(AEOLIA_AHCI_BAR_IDP, PCI_BASE_ADDRESS_SPACE_IO, ahci->_idp); 25 | register_bar(AEOLIA_AHCI_BAR_MEM, PCI_BASE_ADDRESS_SPACE_MEM, ahci->_mem); 26 | 27 | reset(); 28 | } 29 | 30 | AeoliaAHCIDevice::~AeoliaAHCIDevice() { 31 | delete ahci; 32 | } 33 | 34 | void AeoliaAHCIDevice::reset() { 35 | // PCI Configuration Space 36 | auto& header = config_header(); 37 | header.command = PCI_COMMAND_IO | PCI_COMMAND_MEMORY; // TODO: Is this needed? 38 | header.header_type |= PCI_HEADER_TYPE_MULTI_FUNCTION; 39 | header.class_prog = 0x02; 40 | 41 | // Add PCIe capability 42 | // TODO: Refactor this code 43 | const auto cap_off = add_capability(PCI_CAP_ID_EXP, 0x14 /* V1 */); 44 | (U16&)config_data[cap_off + 2 /*PCI_EXP_FLAGS*/ ] = 0x0001; 45 | (U32&)config_data[cap_off + 4 /*PCI_EXP_DEVCAP*/] = 0; 46 | (U16&)config_data[cap_off + 8 /*PCI_EXP_DEVCTL*/] = 0; 47 | (U16&)config_data[cap_off + 10 /*PCI_EXP_DEVSTA*/] = 0; 48 | (U32&)config_data[cap_off + 12 /*PCI_EXP_LNKCAP*/] = 0; 49 | (U16&)config_data[cap_off + 16 /*PCI_EXP_LNKCTL*/] = 0; 50 | (U16&)config_data[cap_off + 18 /*PCI_EXP_LNKSTA*/] = 0; 51 | 52 | ahci->reset(); 53 | } 54 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_ahci.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia AHCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | enum { 16 | AEOLIA_AHCI_DEV = 0x14, 17 | AEOLIA_AHCI_FNC = 0x2, 18 | }; 19 | 20 | constexpr auto AEOLIA_AHCI_VID = static_cast(0x104D); 21 | constexpr auto AEOLIA_AHCI_DID = static_cast(0x909F); 22 | 23 | struct AeoliaAHCIDeviceConfig : PCIeDeviceConfig { 24 | AeoliaAHCIDeviceConfig(PCI_DF df = PCI_DF(AEOLIA_AHCI_DEV, AEOLIA_AHCI_FNC)) 25 | : PCIeDeviceConfig(df, AEOLIA_AHCI_VID, AEOLIA_AHCI_DID, 0x0, PCI_CLASS_SYSTEM_OTHER) { 26 | } 27 | }; 28 | 29 | class AeoliaAHCIDevice final : public PCIeDevice { 30 | public: 31 | AeoliaAHCIDevice(PCIeBus* bus, const AeoliaAHCIDeviceConfig& config = {}); 32 | ~AeoliaAHCIDevice(); 33 | 34 | // Device interface 35 | void reset() override; 36 | 37 | private: 38 | AHCIDevice* ahci; 39 | }; 40 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_dmac.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia DMAC device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "aeolia_dmac.h" 12 | 13 | AeoliaDMACDevice::AeoliaDMACDevice(PCIeBus* bus, const AeoliaDMACDeviceConfig& config) 14 | : PCIeDevice(bus, config) { 15 | // Define BARs 16 | bar0 = new MemorySpace(this, 0x1000, { 17 | static_cast(&AeoliaDMACDevice::bar0_read), 18 | static_cast(&AeoliaDMACDevice::bar0_write), 19 | }); 20 | bar2 = new MemorySpace(this, 0x1000, { 21 | static_cast(&AeoliaDMACDevice::bar2_read), 22 | static_cast(&AeoliaDMACDevice::bar2_write), 23 | }); 24 | 25 | // Register BARs 26 | register_bar(0, PCI_BASE_ADDRESS_SPACE_MEM, bar0); 27 | register_bar(2, PCI_BASE_ADDRESS_SPACE_MEM, bar2); 28 | 29 | #if 0 30 | msi_init(dev, 0x50, 1, true, false, NULL); 31 | if (pci_is_express(dev)) { 32 | pcie_endpoint_cap_init(dev, 0x70); 33 | } 34 | #endif 35 | 36 | reset(); 37 | } 38 | 39 | AeoliaDMACDevice::~AeoliaDMACDevice() { 40 | delete bar0; 41 | delete bar2; 42 | } 43 | 44 | void AeoliaDMACDevice::reset() { 45 | // PCI Configuration Space 46 | auto& header = config_header(); 47 | header.command = PCI_COMMAND_MEMORY; // TODO: Is this needed? 48 | header.header_type |= PCI_HEADER_TYPE_MULTI_FUNCTION; 49 | header.class_prog = 0x05; 50 | 51 | // Add PCIe capability 52 | // TODO: Refactor this code 53 | const auto cap_off = add_capability(PCI_CAP_ID_EXP, 0x14 /* V1 */); 54 | (U16&)config_data[cap_off + 2 /*PCI_EXP_FLAGS*/ ] = 0x0001; 55 | (U32&)config_data[cap_off + 4 /*PCI_EXP_DEVCAP*/] = 0; 56 | (U16&)config_data[cap_off + 8 /*PCI_EXP_DEVCTL*/] = 0; 57 | (U16&)config_data[cap_off + 10 /*PCI_EXP_DEVSTA*/] = 0; 58 | (U32&)config_data[cap_off + 12 /*PCI_EXP_LNKCAP*/] = 0; 59 | (U16&)config_data[cap_off + 16 /*PCI_EXP_LNKCTL*/] = 0; 60 | (U16&)config_data[cap_off + 18 /*PCI_EXP_LNKSTA*/] = 0; 61 | } 62 | 63 | U64 AeoliaDMACDevice::bar0_read(U64 addr, U64 size) { 64 | //assert_always("Unimplemented"); 65 | return 0; 66 | } 67 | 68 | void AeoliaDMACDevice::bar0_write(U64 addr, U64 value, U64 size) { 69 | //assert_always("Unimplemented"); 70 | } 71 | 72 | U64 AeoliaDMACDevice::bar2_read(U64 addr, U64 size) { 73 | assert_always("Unimplemented"); 74 | return 0; 75 | } 76 | 77 | void AeoliaDMACDevice::bar2_write(U64 addr, U64 value, U64 size) { 78 | assert_always("Unimplemented"); 79 | } 80 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_dmac.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia DMAC device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | enum { 16 | AEOLIA_DMAC_DEV = 0x14, 17 | AEOLIA_DMAC_FNC = 0x5, 18 | }; 19 | 20 | constexpr auto AEOLIA_DMAC_VID = static_cast(0x104D); 21 | constexpr auto AEOLIA_DMAC_DID = static_cast(0x90A2); 22 | 23 | struct AeoliaDMACDeviceConfig : PCIeDeviceConfig { 24 | AeoliaDMACDeviceConfig(PCI_DF df = PCI_DF(AEOLIA_DMAC_DEV, AEOLIA_DMAC_FNC)) 25 | : PCIeDeviceConfig(df, AEOLIA_DMAC_VID, AEOLIA_DMAC_DID, 0x0, PCI_CLASS_SYSTEM_OTHER) { 26 | } 27 | }; 28 | 29 | class AeoliaDMACDevice final : public PCIeDevice { 30 | public: 31 | AeoliaDMACDevice(PCIeBus* bus, const AeoliaDMACDeviceConfig& config = {}); 32 | ~AeoliaDMACDevice(); 33 | 34 | // Device interface 35 | void reset() override; 36 | 37 | private: 38 | MemorySpace* bar0; 39 | MemorySpace* bar2; 40 | 41 | U64 bar0_read(U64 addr, U64 size); 42 | void bar0_write(U64 addr, U64 value, U64 size); 43 | 44 | U64 bar2_read(U64 addr, U64 size); 45 | void bar2_write(U64 addr, U64 value, U64 size); 46 | }; 47 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_gbe.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia GBE device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "aeolia_gbe.h" 12 | 13 | // Logging 14 | #define DEBUG_GBE 0 15 | #define DPRINTF(...) \ 16 | do { \ 17 | if (DEBUG_GBE) { \ 18 | fprintf(stderr, "aeolia-gbe (%s:%d): ", __FUNCTION__, __LINE__); \ 19 | fprintf(stderr, __VA_ARGS__); \ 20 | fprintf(stderr, "\n"); \ 21 | } \ 22 | } while (0) 23 | 24 | enum { 25 | AGBE_DEVICE_ID = 0x011B, 26 | AGBE_DEVICE_REV = 0x011A, 27 | AGBE_UNK2880 = 0x2880, 28 | }; 29 | 30 | AeoliaGBEDevice::AeoliaGBEDevice(PCIeBus* bus, const AeoliaGBEDeviceConfig& config) 31 | : PCIeDevice(bus, config) { 32 | // Define BARs 33 | mmio = new MemorySpace(this, 0x4000, { 34 | static_cast(&AeoliaGBEDevice::mmio_read), 35 | static_cast(&AeoliaGBEDevice::mmio_write), 36 | }); 37 | 38 | // Register BARs 39 | register_bar(0, PCI_BASE_ADDRESS_SPACE_MEM, mmio); 40 | 41 | #if 0 42 | msi_init(dev, 0x50, 1, true, false, NULL); 43 | if (pci_is_express(dev)) { 44 | pcie_endpoint_cap_init(dev, 0x70); 45 | } 46 | #endif 47 | 48 | reset(); 49 | } 50 | 51 | AeoliaGBEDevice::~AeoliaGBEDevice() { 52 | } 53 | 54 | void AeoliaGBEDevice::reset() { 55 | // PCI Configuration Space 56 | auto& header = config_header(); 57 | header.command = PCI_COMMAND_MEMORY; // TODO: Is this needed? 58 | header.header_type |= PCI_HEADER_TYPE_MULTI_FUNCTION; 59 | header.class_prog = 0x01; 60 | 61 | // Add PCIe capability 62 | // TODO: Refactor this code 63 | const auto cap_off = add_capability(PCI_CAP_ID_EXP, 0x14 /* V1 */); 64 | (U16&)config_data[cap_off + 2 /*PCI_EXP_FLAGS*/ ] = 0x0001; 65 | (U32&)config_data[cap_off + 4 /*PCI_EXP_DEVCAP*/] = 0; 66 | (U16&)config_data[cap_off + 8 /*PCI_EXP_DEVCTL*/] = 0; 67 | (U16&)config_data[cap_off + 10 /*PCI_EXP_DEVSTA*/] = 0; 68 | (U32&)config_data[cap_off + 12 /*PCI_EXP_LNKCAP*/] = 0; 69 | (U16&)config_data[cap_off + 16 /*PCI_EXP_LNKCTL*/] = 0; 70 | (U16&)config_data[cap_off + 18 /*PCI_EXP_LNKSTA*/] = 0; 71 | } 72 | 73 | U64 AeoliaGBEDevice::mmio_read(U64 addr, U64 size) { 74 | U64 value = 0; 75 | assert_always("Unimplemented"); 76 | 77 | DPRINTF("addr=0x%llX, size=0x%llX\n", addr, size); 78 | switch (addr) { 79 | case AGBE_DEVICE_ID: 80 | assert(size == 1); 81 | value = 0xBD; 82 | break; 83 | case AGBE_DEVICE_REV: 84 | assert(size == 1); 85 | value = 0x00; // TODO 86 | break; 87 | case AGBE_UNK2880: 88 | assert(size == 2); 89 | value = 0x10; // TODO 90 | break; 91 | } 92 | return value; 93 | } 94 | 95 | void AeoliaGBEDevice::mmio_write(U64 addr, U64 value, U64 size) { 96 | assert_always("Unimplemented"); 97 | } 98 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_gbe.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia GBE device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | enum { 16 | AEOLIA_GBE_DEV = 0x14, 17 | AEOLIA_GBE_FNC = 0x1, 18 | }; 19 | 20 | constexpr auto AEOLIA_GBE_VID = static_cast(0x104D); 21 | constexpr auto AEOLIA_GBE_DID = static_cast(0x909E); 22 | 23 | struct AeoliaGBEDeviceConfig : PCIeDeviceConfig { 24 | AeoliaGBEDeviceConfig(PCI_DF df = PCI_DF(AEOLIA_GBE_DEV, AEOLIA_GBE_FNC)) 25 | : PCIeDeviceConfig(df, AEOLIA_GBE_VID, AEOLIA_GBE_DID, 0x0, PCI_CLASS_SYSTEM_OTHER) { 26 | } 27 | }; 28 | 29 | class AeoliaGBEDevice final : public PCIeDevice { 30 | public: 31 | AeoliaGBEDevice(PCIeBus* bus, const AeoliaGBEDeviceConfig& config = {}); 32 | ~AeoliaGBEDevice(); 33 | 34 | // Device interface 35 | void reset() override; 36 | 37 | private: 38 | MemorySpace* mmio; 39 | 40 | U64 mmio_read(U64 addr, U64 size); 41 | void mmio_write(U64 addr, U64 value, U64 size); 42 | }; 43 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_mem.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia memory device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "aeolia_mem.h" 12 | 13 | constexpr U32 AMEM_SPM_VERSION_MAJOR = 0x12010; 14 | constexpr U32 AMEM_SPM_VERSION_MINOR = 0x12011; 15 | constexpr U32 AMEM_SPM_VERSION_REV = 0x12012; 16 | 17 | AeoliaMemDevice::AeoliaMemDevice(PCIeBus* bus, const AeoliaMemDeviceConfig& config) 18 | : PCIeDevice(bus, config) { 19 | // Define BARs 20 | bar0 = new MemorySpace(this, 0x1000, { 21 | static_cast(&AeoliaMemDevice::bar0_read), 22 | static_cast(&AeoliaMemDevice::bar0_write), 23 | }); 24 | bar2 = new MemorySpace(this, 0x40000000, { 25 | static_cast(&AeoliaMemDevice::bar2_read), 26 | static_cast(&AeoliaMemDevice::bar2_write), 27 | }); 28 | bar4 = new MemorySpace(this, 0x100000, { 29 | static_cast(&AeoliaMemDevice::bar4_read), 30 | static_cast(&AeoliaMemDevice::bar4_write), 31 | }); 32 | spm = new MemorySpace(this, 0x40000); 33 | 34 | // Register BARs 35 | register_bar(0, PCI_BASE_ADDRESS_SPACE_MEM, bar0); 36 | register_bar(2, PCI_BASE_ADDRESS_SPACE_MEM, bar2); 37 | register_bar(4, PCI_BASE_ADDRESS_SPACE_MEM, bar4); 38 | register_bar(5, PCI_BASE_ADDRESS_SPACE_MEM, spm); 39 | 40 | reset(); 41 | } 42 | 43 | AeoliaMemDevice::~AeoliaMemDevice() { 44 | delete bar0; 45 | delete bar2; 46 | delete bar4; 47 | delete spm; 48 | } 49 | 50 | void AeoliaMemDevice::reset() { 51 | // PCI Configuration Space 52 | auto& header = config_header(); 53 | header.command = PCI_COMMAND_MEMORY; // TODO: Is this needed? 54 | header.header_type |= PCI_HEADER_TYPE_MULTI_FUNCTION; 55 | header.class_prog = 0x06; 56 | header.intr_line = 0xFF; 57 | header.intr_pin = 0x00; 58 | 59 | // Init SPM 60 | auto data = reinterpret_cast(spm->ptr()); 61 | 62 | // Subsystem ID 63 | // Written in big-endian. Hardcoded to 0x10200 for now. 64 | // - 0x1XXXX Aeolia 65 | // - 0x2XXXX Belize 66 | // - 0x3XXXX Baikal 67 | // - 0x4XXXX Belize 68 | data[AMEM_SPM_VERSION_MAJOR] = 0x1; 69 | data[AMEM_SPM_VERSION_MINOR] = 0x2; 70 | data[AMEM_SPM_VERSION_REV] = 0x0; 71 | } 72 | 73 | U64 AeoliaMemDevice::bar0_read(U64 addr, U64 size) { 74 | assert_always("Unimplemented"); 75 | return 0; 76 | } 77 | 78 | void AeoliaMemDevice::bar0_write(U64 addr, U64 value, U64 size) { 79 | assert_always("Unimplemented"); 80 | } 81 | 82 | U64 AeoliaMemDevice::bar2_read(U64 addr, U64 size) { 83 | assert_always("Unimplemented"); 84 | return 0; 85 | } 86 | 87 | void AeoliaMemDevice::bar2_write(U64 addr, U64 value, U64 size) { 88 | assert_always("Unimplemented"); 89 | } 90 | 91 | U64 AeoliaMemDevice::bar4_read(U64 addr, U64 size) { 92 | assert_always("Unimplemented"); 93 | return 0; 94 | } 95 | 96 | void AeoliaMemDevice::bar4_write(U64 addr, U64 value, U64 size) { 97 | assert_always("Unimplemented"); 98 | } 99 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_mem.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia memory device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | enum { 16 | AEOLIA_MEM_DEV = 0x14, 17 | AEOLIA_MEM_FNC = 0x6, 18 | }; 19 | 20 | constexpr U32 ASPM_ICC_BASE = 0;// 0x2C000; 21 | constexpr U32 ASPM_ICC_SIZE = 0x1000; 22 | constexpr U32 ASPM_ICC_QUERY = ASPM_ICC_BASE + 0x000; 23 | constexpr U32 ASPM_ICC_QUERY_W = ASPM_ICC_BASE + 0x7F0; 24 | constexpr U32 ASPM_ICC_QUERY_R = ASPM_ICC_BASE + 0x7F4; 25 | constexpr U32 ASPM_ICC_REPLY = ASPM_ICC_BASE + 0x800; 26 | constexpr U32 ASPM_ICC_REPLY_W = ASPM_ICC_BASE + 0xFF0; 27 | constexpr U32 ASPM_ICC_REPLY_R = ASPM_ICC_BASE + 0xFF4; 28 | 29 | constexpr auto AEOLIA_MEM_VID = static_cast(0x104D); 30 | constexpr auto AEOLIA_MEM_DID = static_cast(0x90A3); 31 | 32 | struct AeoliaMemDeviceConfig : PCIeDeviceConfig { 33 | AeoliaMemDeviceConfig(PCI_DF df = PCI_DF(AEOLIA_MEM_DEV, AEOLIA_MEM_FNC)) 34 | : PCIeDeviceConfig(df, AEOLIA_MEM_VID, AEOLIA_MEM_DID, 0x0, PCI_CLASS_SYSTEM_OTHER) { 35 | } 36 | }; 37 | 38 | class AeoliaMemDevice final : public PCIeDevice { 39 | public: 40 | AeoliaMemDevice(PCIeBus* bus, const AeoliaMemDeviceConfig& config = {}); 41 | ~AeoliaMemDevice(); 42 | 43 | // Device interface 44 | void reset() override; 45 | 46 | MemorySpace* get_spm() { 47 | return spm; 48 | } 49 | 50 | private: 51 | MemorySpace* bar0; 52 | MemorySpace* bar2; 53 | MemorySpace* bar4; 54 | MemorySpace* spm; 55 | 56 | U64 bar0_read(U64 addr, U64 size); 57 | void bar0_write(U64 addr, U64 value, U64 size); 58 | 59 | U64 bar2_read(U64 addr, U64 size); 60 | void bar2_write(U64 addr, U64 value, U64 size); 61 | 62 | U64 bar4_read(U64 addr, U64 size); 63 | void bar4_write(U64 addr, U64 value, U64 size); 64 | }; 65 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_pcie.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia PCIe device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include "icc/icc.h" 14 | #include "hpet/aeolia_hpet.h" 15 | #include "msic/aeolia_msic.h" 16 | #include "nvs/aeolia_nvs.h" 17 | 18 | #include 19 | 20 | #include 21 | 22 | // Forward declarations 23 | class AeoliaUARTDevice; 24 | 25 | enum { 26 | AEOLIA_PCIE_DEV = 0x14, 27 | AEOLIA_PCIE_FNC = 0x4, 28 | }; 29 | 30 | constexpr auto AEOLIA_PCIE_VID = static_cast(0x104D); 31 | constexpr auto AEOLIA_PCIE_DID = static_cast(0x90A1); 32 | 33 | struct AeoliaPCIeDeviceConfig : PCIeDeviceConfig { 34 | CharHost* backend_uart0 = nullptr; 35 | CharHost* backend_uart1 = nullptr; 36 | 37 | AeoliaPCIeDeviceConfig(PCI_DF df = PCI_DF(AEOLIA_PCIE_DEV, AEOLIA_PCIE_FNC)) 38 | : PCIeDeviceConfig(df, AEOLIA_PCIE_VID, AEOLIA_PCIE_DID, 0x0, PCI_CLASS_SYSTEM_OTHER) { 39 | } 40 | }; 41 | 42 | class AeoliaPCIeDevice final : public PCIeDevice { 43 | public: 44 | AeoliaPCIeDevice(PCIeBus* bus, const AeoliaPCIeDeviceConfig& config = {}); 45 | ~AeoliaPCIeDevice(); 46 | 47 | // Device interface 48 | void reset() override; 49 | 50 | void set_spm(MemorySpace* spm) { 51 | this->spm = spm; 52 | } 53 | 54 | private: 55 | MemorySpace* bar0; 56 | MemorySpace* bar2; 57 | MemorySpace* mmio_peripherals; 58 | MemorySpace* spm; // Not owned 59 | 60 | std::unique_ptr uart0; 61 | std::unique_ptr uart1; 62 | 63 | // State 64 | AeoliaHpet hpet; 65 | AeoliaMsic msic; 66 | AeoliaNVS nvs{}; 67 | uint32_t icc_doorbell; 68 | uint32_t icc_status; 69 | struct AeoliaPCIeBar { 70 | uint32_t size; 71 | uint32_t base; 72 | } bars[0x40] = {}; 73 | 74 | U64 bar0_read(U64 addr, U64 size); 75 | void bar0_write(U64 addr, U64 value, U64 size); 76 | 77 | U64 bar2_read(U64 addr, U64 size); 78 | void bar2_write(U64 addr, U64 value, U64 size); 79 | 80 | U64 peripherals_read(U64 addr, U64 size); 81 | void peripherals_write(U64 addr, U64 value, U64 size); 82 | 83 | // Updates 84 | void update_bars(); 85 | void update_icc(); 86 | 87 | // ICC 88 | using IccReply = std::pair; 89 | IccReply icc_cmd_service_version(); 90 | IccReply icc_cmd_board_id(); 91 | IccReply icc_cmd_board_version(IccReplyBoardVersion& reply); 92 | IccReply icc_cmd_board_capacity(IccReplyBoardCapacity& reply); 93 | IccReply icc_cmd_buttons_state(); 94 | IccReply icc_cmd_nvram_write(const IccQueryNvram& query); 95 | IccReply icc_cmd_nvram_read(const IccQueryNvram& query, IccReplyMessage& reply); 96 | }; 97 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_sdhci.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia SDHCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "aeolia_sdhci.h" 12 | 13 | AeoliaSDHCIDevice::AeoliaSDHCIDevice(PCIeBus* bus, const AeoliaSDHCIDeviceConfig& config) 14 | : PCIeDevice(bus, config) { 15 | // Define BARs 16 | mmio = new MemorySpace(this, 0x1000, { 17 | static_cast(&AeoliaSDHCIDevice::mmio_read), 18 | static_cast(&AeoliaSDHCIDevice::mmio_write), 19 | }); 20 | 21 | // Register BARs 22 | register_bar(0, PCI_BASE_ADDRESS_SPACE_MEM, mmio); 23 | 24 | reset(); 25 | } 26 | 27 | AeoliaSDHCIDevice::~AeoliaSDHCIDevice() { 28 | } 29 | 30 | void AeoliaSDHCIDevice::reset() { 31 | // PCI Configuration Space 32 | auto& header = config_header(); 33 | header.command = PCI_COMMAND_MEMORY; // TODO: Is this needed? 34 | header.header_type |= PCI_HEADER_TYPE_MULTI_FUNCTION; 35 | header.class_prog = 0x03; 36 | msi_enable(1, true); 37 | 38 | // Add PCIe capability 39 | // TODO: Refactor this code 40 | const auto cap_off = add_capability(PCI_CAP_ID_EXP, 0x14 /* V1 */, 0x70); 41 | (U16&)config_data[cap_off + 2 /*PCI_EXP_FLAGS*/ ] = 0x0001; 42 | (U32&)config_data[cap_off + 4 /*PCI_EXP_DEVCAP*/] = 0; 43 | (U16&)config_data[cap_off + 8 /*PCI_EXP_DEVCTL*/] = 0; 44 | (U16&)config_data[cap_off + 10 /*PCI_EXP_DEVSTA*/] = 0; 45 | (U32&)config_data[cap_off + 12 /*PCI_EXP_LNKCAP*/] = 0; 46 | (U16&)config_data[cap_off + 16 /*PCI_EXP_LNKCTL*/] = 0; 47 | (U16&)config_data[cap_off + 18 /*PCI_EXP_LNKSTA*/] = 0; 48 | } 49 | 50 | U64 AeoliaSDHCIDevice::mmio_read(U64 addr, U64 size) { 51 | U64 value = 0; 52 | assert_always("Unimplemented"); 53 | 54 | return value; 55 | } 56 | 57 | void AeoliaSDHCIDevice::mmio_write(U64 addr, U64 value, U64 size) { 58 | assert_always("Unimplemented"); 59 | } 60 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_sdhci.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia SDHCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | enum { 16 | AEOLIA_SDHCI_DEV = 0x14, 17 | AEOLIA_SDHCI_FNC = 0x3, 18 | }; 19 | 20 | constexpr auto AEOLIA_SDHCI_VID = static_cast(0x104D); 21 | constexpr auto AEOLIA_SDHCI_DID = static_cast(0x90A0); 22 | 23 | struct AeoliaSDHCIDeviceConfig : PCIeDeviceConfig { 24 | AeoliaSDHCIDeviceConfig(PCI_DF df = PCI_DF(AEOLIA_SDHCI_DEV, AEOLIA_SDHCI_FNC)) 25 | : PCIeDeviceConfig(df, AEOLIA_SDHCI_VID, AEOLIA_SDHCI_DID, 0x0, PCI_CLASS_SYSTEM_OTHER) { 26 | } 27 | }; 28 | 29 | class AeoliaSDHCIDevice final : public PCIeDevice { 30 | public: 31 | AeoliaSDHCIDevice(PCIeBus* bus, const AeoliaSDHCIDeviceConfig& config = {}); 32 | ~AeoliaSDHCIDevice(); 33 | 34 | // Device interface 35 | void reset() override; 36 | 37 | private: 38 | MemorySpace* mmio; 39 | 40 | U64 mmio_read(U64 addr, U64 size); 41 | void mmio_write(U64 addr, U64 value, U64 size); 42 | }; 43 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_xhci.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia XHCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "aeolia_xhci.h" 12 | 13 | AeoliaXHCIDevice::AeoliaXHCIDevice(PCIeBus* bus, const AeoliaXHCIDeviceConfig& config) 14 | : PCIeDevice(bus, config) { 15 | // Define BARs 16 | constexpr size_t xhci_size = 0x200000; 17 | xhci[0] = new MemorySpace(this, xhci_size, { 18 | static_cast(&AeoliaXHCIDevice::xhci0_read), 19 | static_cast(&AeoliaXHCIDevice::xhci0_write), 20 | }); 21 | xhci[1] = new MemorySpace(this, xhci_size, { 22 | static_cast(&AeoliaXHCIDevice::xhci1_read), 23 | static_cast(&AeoliaXHCIDevice::xhci1_write), 24 | }); 25 | xhci[2] = new MemorySpace(this, xhci_size, { 26 | static_cast(&AeoliaXHCIDevice::xhci2_read), 27 | static_cast(&AeoliaXHCIDevice::xhci2_write), 28 | }); 29 | 30 | // Register BARs 31 | register_bar(0, PCI_BASE_ADDRESS_SPACE_MEM, xhci[0]); 32 | register_bar(2, PCI_BASE_ADDRESS_SPACE_MEM, xhci[1]); 33 | register_bar(4, PCI_BASE_ADDRESS_SPACE_MEM, xhci[2]); 34 | 35 | reset(); 36 | } 37 | 38 | AeoliaXHCIDevice::~AeoliaXHCIDevice() { 39 | } 40 | 41 | void AeoliaXHCIDevice::reset() { 42 | // PCI Configuration Space 43 | auto& header = config_header(); 44 | header.command = PCI_COMMAND_MEMORY; // TODO: Is this needed? 45 | header.header_type |= PCI_HEADER_TYPE_MULTI_FUNCTION; 46 | header.class_prog = 0x30; // TODO: Is this correct? 47 | } 48 | 49 | U64 AeoliaXHCIDevice::xhci0_read(U64 addr, U64 size) { 50 | assert_always("Unimplemented"); 51 | return 0; 52 | } 53 | 54 | void AeoliaXHCIDevice::xhci0_write(U64 addr, U64 value, U64 size) { 55 | assert_always("Unimplemented"); 56 | } 57 | 58 | U64 AeoliaXHCIDevice::xhci1_read(U64 addr, U64 size) { 59 | assert_always("Unimplemented"); 60 | return 0; 61 | } 62 | 63 | void AeoliaXHCIDevice::xhci1_write(U64 addr, U64 value, U64 size) { 64 | assert_always("Unimplemented"); 65 | } 66 | 67 | U64 AeoliaXHCIDevice::xhci2_read(U64 addr, U64 size) { 68 | assert_always("Unimplemented"); 69 | return 0; 70 | } 71 | 72 | void AeoliaXHCIDevice::xhci2_write(U64 addr, U64 value, U64 size) { 73 | assert_always("Unimplemented"); 74 | } 75 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/aeolia_xhci.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia XHCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | enum { 16 | AEOLIA_XHCI_DEV = 0x14, 17 | AEOLIA_XHCI_FNC = 0x7, 18 | }; 19 | 20 | constexpr auto AEOLIA_XHCI_VID = static_cast(0x104D); 21 | constexpr auto AEOLIA_XHCI_DID = static_cast(0x90A4); 22 | 23 | struct AeoliaXHCIDeviceConfig : PCIeDeviceConfig { 24 | AeoliaXHCIDeviceConfig(PCI_DF df = PCI_DF(AEOLIA_XHCI_DEV, AEOLIA_XHCI_FNC)) 25 | : PCIeDeviceConfig(df, AEOLIA_XHCI_VID, AEOLIA_XHCI_DID, 0x0, PCI_CLASS_SYSTEM_OTHER) { 26 | } 27 | }; 28 | 29 | class AeoliaXHCIDevice final : public PCIeDevice { 30 | public: 31 | AeoliaXHCIDevice(PCIeBus* bus, const AeoliaXHCIDeviceConfig& config = {}); 32 | ~AeoliaXHCIDevice(); 33 | 34 | // Device interface 35 | void reset() override; 36 | 37 | private: 38 | MemorySpace* xhci[3]; 39 | 40 | U64 xhci0_read(U64 addr, U64 size); 41 | void xhci0_write(U64 addr, U64 value, U64 size); 42 | 43 | U64 xhci1_read(U64 addr, U64 size); 44 | void xhci1_write(U64 addr, U64 value, U64 size); 45 | 46 | U64 xhci2_read(U64 addr, U64 size); 47 | void xhci2_write(U64 addr, U64 value, U64 size); 48 | }; 49 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/hpet/aeolia_hpet.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia High-Precision Event Timer (HPET) device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | struct HPETTimer { 16 | union { 17 | U64 value; 18 | struct { 19 | U32 value_lo; 20 | U32 value_hi; 21 | }; 22 | Bit int_type_cnf; 23 | Bit int_enb_cnf; 24 | Bit type_cnf; 25 | Bit per_int_cap; 26 | Bit size_cap; 27 | Bit val_set_cnf; 28 | Bit mode32_cnf; 29 | Bitrange int_route_cnf; 30 | Bitrange fsb_en_cnf; 31 | Bitrange fsb_int_del_cap; 32 | Bitrange int_route_cap; 33 | } config; 34 | U64 comparator; 35 | union { 36 | U64 value; 37 | struct { 38 | U32 int_val; 39 | U32 int_addr; 40 | }; 41 | } fsb; 42 | }; 43 | 44 | struct AeoliaHpetConfig : DeviceConfig { 45 | U64 base = 0xFED00000; 46 | U64 count = 4; 47 | U64 period_fs = 100 * 1000000; // 100ns 48 | }; 49 | 50 | class AeoliaHpet : public Device { 51 | public: 52 | AeoliaHpet(ContainerSpace* mem, const AeoliaHpetConfig& config = {}); 53 | ~AeoliaHpet(); 54 | 55 | void reset() override; 56 | 57 | U64 mmio_read(U64 addr, U64 size); 58 | void mmio_write(U64 addr, U64 value, U64 size); 59 | 60 | private: 61 | Space* mem; 62 | MemorySpace* mmio; 63 | std::vector timers; 64 | 65 | struct { 66 | union { 67 | U64 value; 68 | struct { 69 | U32 value_lo; 70 | U32 value_hi; 71 | }; 72 | Bitrange rev_id; 73 | Bitrange num_tim_cap; 74 | Bitrange count_size_cap; 75 | Bitrange leg_rt_cap; 76 | Bitrange vendor_id; 77 | Bitrange period; 78 | } cap; 79 | union { 80 | U64 value; 81 | struct { 82 | U32 value_lo; 83 | U32 value_hi; 84 | }; 85 | Bit leg_rt_cnf; 86 | Bit enable_cnf; 87 | } config; 88 | union { 89 | U64 value; 90 | struct { 91 | U32 value_lo; 92 | U32 value_hi; 93 | }; 94 | Bitset<64> tn_int_sts; 95 | } isr; 96 | union { 97 | U64 value; 98 | struct { 99 | U32 lo; 100 | U32 hi; 101 | }; 102 | } counter; 103 | } s = {}; 104 | 105 | // Helpers 106 | U64 get_counter(); 107 | U64 get_ticks(); 108 | 109 | // Interrupts 110 | void update_irq(HPETTimer& timer, bool set); 111 | }; 112 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/msic/aeolia_msic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia MSI Controller (MSIC) device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | // List of subfunctions for function #4 (PCIe) 16 | #define APCIE_MSI_FNC4_GLUE 0 17 | #define APCIE_MSI_FNC4_ICC 3 18 | #define APCIE_MSI_FNC4_HPET 5 19 | #define APCIE_MSI_FNC4_SFLASH 11 20 | #define APCIE_MSI_FNC4_RTC 13 21 | #define APCIE_MSI_FNC4_UART0 19 22 | #define APCIE_MSI_FNC4_UART1 20 23 | #define APCIE_MSI_FNC4_TWSI 21 24 | 25 | // List of subfunctions for function #7 (XHCI) 26 | #define APCIE_MSI_FNC7_XHCI0 0 27 | #define APCIE_MSI_FNC7_XHCI1 1 28 | #define APCIE_MSI_FNC7_XHCI2 2 29 | 30 | class AeoliaMsic : public Device { 31 | public: 32 | AeoliaMsic(Space* mem); 33 | 34 | void reset(); 35 | 36 | /** 37 | * Perform 32-bit MMIO read at an offset relative to the MSI controller base. 38 | * @param[in] offset Offset to read from 39 | * @return Value read 40 | */ 41 | U32 mmio_read(U32 index); 42 | 43 | /** 44 | * Perform 32-bit MMIO write at an offset relative to the MSI controller base. 45 | * @param[in] offset Offset to write to 46 | * @param[in] value Value to be written 47 | */ 48 | void mmio_write(U32 offset, U32 value); 49 | 50 | /** 51 | * Send an interrupt to the CPU given a function:subfunction. 52 | * @param[in] func Function identifier 53 | * @param[in] sub Subfunction identifier 54 | */ 55 | void msi_trigger(U32 func, U32 sub); 56 | 57 | private: 58 | Space* mem; 59 | 60 | U32 func_addr[8]; 61 | U32 func_mask[8]; 62 | U32 func_data[8]; 63 | union { 64 | struct { 65 | U32 func0_data_lo[4]; 66 | U32 func1_data_lo[4]; 67 | U32 func2_data_lo[4]; 68 | U32 func3_data_lo[4]; 69 | U32 func4_data_lo[24]; 70 | U32 func5_data_lo[4]; 71 | U32 func6_data_lo[4]; 72 | U32 func7_data_lo[4]; 73 | }; 74 | U32 data_lo[52]; 75 | }; 76 | }; 77 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/nvs/aeolia_nvs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia Non-Volatile Storage (NVS). 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | #include 16 | 17 | #define NVS_RANGE(base, size, ...) \ 18 | struct { std::array _; union { std::array data; struct { __VA_ARGS__ }; }; } 19 | 20 | struct AeoliaNVS { 21 | union { 22 | U08 data[0x400]; 23 | union { 24 | // [0x9B330, 0x9B34F] 25 | NVS_RANGE(0x000, 0x20) OsBootParameter; 26 | // [0x9B350, 0x9B38F] 27 | NVS_RANGE(0x000, 0x40) LsiBootParameter; 28 | // [0x9B390, 0x9B48F] 29 | NVS_RANGE(0x300, 0x100) BiosConfig; 30 | // [0x9B6E4, 0x9B743] 31 | NVS_RANGE(0x200, 0x60) EapPartitionKey; 32 | // 0x9B6DD 33 | NVS_RANGE(0x065, 0x1) CsBackupMode; 34 | // 0x9B6DE 35 | NVS_RANGE(0x0C0, 0x2) TempSlewRate; 36 | }; 37 | }; 38 | 39 | AeoliaNVS() { 40 | memset(data, 0, sizeof(data)); 41 | 42 | OsBootParameter.data[0x18] = 2; // sceKernelHwHasWlanBt second bit as 1 for none 43 | BiosConfig.data[0] = 0xF0; // verbose ubios boot 44 | } 45 | 46 | constexpr size_t size() const noexcept { 47 | return sizeof(AeoliaNVS); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /src/orbital/hardware/aeolia/uart/aeolia_uart.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Aeolia UART device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | struct AeoliaUARTDeviceConfig : DeviceConfig { 16 | CharHost* backend = nullptr; 17 | 18 | AeoliaUARTDeviceConfig(CharHost* backend = nullptr) 19 | : backend(backend) { 20 | } 21 | }; 22 | 23 | class AeoliaUARTDevice final : public Device { 24 | public: 25 | AeoliaUARTDevice(Device* parent, Interrupt* irq, const AeoliaUARTDeviceConfig& config = {}); 26 | ~AeoliaUARTDevice(); 27 | 28 | void reset() override; 29 | 30 | // Helpers 31 | MemorySpace* io() const { 32 | return space_io; 33 | } 34 | 35 | private: 36 | Interrupt* irq; 37 | 38 | FIFO fifo_rx; 39 | FIFO fifo_tx; 40 | bool thre_intr_pending = false; 41 | struct { 42 | U8 thr; // Transmitter Holding Register 43 | U8 rbr; // Receiver Buffer Register 44 | U8 ier; // Interrupt Enable Register 45 | U8 iir; // Interrupt Identification Register 46 | U8 lcr; // Line Control Register 47 | U8 mcr; // Modem Control Register 48 | U8 lsr; // Line Status Register 49 | U8 msr; // Modem Status Register 50 | U8 scr; // Scratch Register 51 | U8 fcr; // FIFO Control Register 52 | union { 53 | U16 div; // Divisor Latch 54 | struct { 55 | U8 dll; 56 | U8 dlh; 57 | }; 58 | }; 59 | } s = {}; 60 | 61 | CharHost* char_backend{ nullptr }; 62 | MemorySpace* space_io{ nullptr }; 63 | 64 | void update_irq(); 65 | 66 | U64 io_read(U64 addr, U64 size); 67 | void io_write(U64 addr, U64 value, U64 size); 68 | }; 69 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/acp/acp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * AMD ACP device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | // ACP Control registers 14 | #define mmACP_CONTROL 0x00005286 15 | #define mmACP_STATUS 0x00005288 16 | #define mmACP_DSP_RUNSTALL 0x00005289 17 | #define mmACP_DSP_VECT_SEL 0x0000528A 18 | #define mmACP_DSP_WAIT_MODE 0x0000528B 19 | #define mmACP_OCD_HALT_ON_RST 0x0000528C 20 | #define mmACP_SOFT_RESET 0x0000528D 21 | 22 | // ACP DMA registers 23 | #define mmACP_DMA_CH_STS 0x000051A0 24 | #define mmACP_DMA_CNTL_(I) (0x00005130 + (I)) 25 | #define mmACP_DMA_CUR_DSCR_(I) (0x00005170 + (I)) 26 | #define mmACP_DMA_CUR_TRANS_CNT_(I) (0x00005180 + (I)) 27 | #define mmACP_DMA_ERR_STS_(I) (0x00005190 + (I)) 28 | 29 | // ACP external interrupt registers 30 | #define mmACP_EXTERNAL_INTR_ENB 0x000051E4 31 | #define mmACP_EXTERNAL_INTR_CNTL 0x000051E5 32 | #define mmACP_EXTERNAL_INTR_STAT 0x000051EA 33 | #define mmACP_DSP_SW_INTR_CNTL 0x000051E8 34 | #define mmACP_DSP_SW_INTR_STAT 0x000051EB 35 | 36 | // ACP unknown regs 37 | #define mmACP_UNK512F_ 0x0000512F 38 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/amd_regs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * AMD utility macros for registers. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #define REG_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT 14 | #define REG_FIELD_MASK(reg, field) reg##__##field##_MASK 15 | 16 | #define REG_SET_FIELD(orig_val, reg, field, field_val) \ 17 | (((orig_val) & ~REG_FIELD_MASK(reg, field)) | \ 18 | (REG_FIELD_MASK(reg, field) & ((field_val) << REG_FIELD_SHIFT(reg, field)))) 19 | 20 | #define REG_GET_FIELD(value, reg, field) \ 21 | (((value) & REG_FIELD_MASK(reg, field)) >> REG_FIELD_SHIFT(reg, field)) 22 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/amd_ucode.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Liverpool F32 ucode utilities. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | template 16 | struct AmdUcode { 17 | U32 data[N]; 18 | U32 addr; 19 | 20 | void push(U32 value) { 21 | data[addr >> 2] = value; 22 | addr += 4; 23 | addr &= N - 1; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/bif/bif_regs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * AMD Bus Interface (BIF) device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include "bif/bif_4_1_d.h" 14 | #include "bif/bif_4_1_sh_mask.h" 15 | 16 | // Undocumented registers 17 | #define mmCC_BIF_SECURE_CNTL 0x14E3 18 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/gca/pm4.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * AMD PM4 packets. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "pm4.h" 12 | 13 | const char* pm4_itop_name(U32 itop) { 14 | #define CASE(itop) case PM4_IT_##itop: return #itop 15 | switch (itop) { 16 | CASE(NOP); 17 | CASE(SET_BASE); 18 | CASE(CLEAR_STATE); 19 | CASE(INDEX_BUFFER_SIZE); 20 | CASE(DISPATCH_DIRECT); 21 | CASE(DISPATCH_INDIRECT); 22 | CASE(ATOMIC_GDS); 23 | CASE(OCCLUSION_QUERY); 24 | CASE(SET_PREDICATION); 25 | CASE(REG_RMW); 26 | CASE(COND_EXEC); 27 | CASE(PRED_EXEC); 28 | CASE(DRAW_INDIRECT); 29 | CASE(DRAW_INDEX_INDIRECT); 30 | CASE(INDEX_BASE); 31 | CASE(DRAW_INDEX_2); 32 | CASE(CONTEXT_CONTROL); 33 | CASE(INDEX_TYPE); 34 | CASE(DRAW_INDIRECT_MULTI); 35 | CASE(DRAW_INDEX_AUTO); 36 | CASE(NUM_INSTANCES); 37 | CASE(DRAW_INDEX_MULTI_AUTO); 38 | CASE(INDIRECT_BUFFER_CONST); 39 | CASE(STRMOUT_BUFFER_UPDATE); 40 | CASE(DRAW_INDEX_OFFSET_2); 41 | CASE(DRAW_PREAMBLE); 42 | CASE(WRITE_DATA); 43 | CASE(DRAW_INDEX_INDIRECT_MULTI); 44 | CASE(MEM_SEMAPHORE); 45 | CASE(COPY_DW); 46 | CASE(WAIT_REG_MEM); 47 | CASE(INDIRECT_BUFFER); 48 | CASE(COPY_DATA); 49 | CASE(PFP_SYNC_ME); 50 | CASE(SURFACE_SYNC); 51 | CASE(COND_WRITE); 52 | CASE(EVENT_WRITE); 53 | CASE(EVENT_WRITE_EOP); 54 | CASE(EVENT_WRITE_EOS); 55 | CASE(RELEASE_MEM); 56 | CASE(PREAMBLE_CNTL); 57 | CASE(DMA_DATA); 58 | CASE(ACQUIRE_MEM); 59 | CASE(REWIND); 60 | CASE(LOAD_UCONFIG_REG); 61 | CASE(LOAD_SH_REG); 62 | CASE(LOAD_CONFIG_REG); 63 | CASE(LOAD_CONTEXT_REG); 64 | CASE(SET_CONFIG_REG); 65 | CASE(SET_CONTEXT_REG); 66 | CASE(SET_CONTEXT_REG_INDIRECT); 67 | CASE(SET_SH_REG); 68 | CASE(SET_SH_REG_OFFSET); 69 | CASE(SET_QUEUE_REG); 70 | CASE(SET_UCONFIG_REG); 71 | CASE(SCRATCH_RAM_WRITE); 72 | CASE(SCRATCH_RAM_READ); 73 | CASE(LOAD_CONST_RAM); 74 | CASE(WRITE_CONST_RAM); 75 | CASE(DUMP_CONST_RAM); 76 | CASE(INCREMENT_CE_COUNTER); 77 | CASE(INCREMENT_DE_COUNTER); 78 | CASE(WAIT_ON_CE_COUNTER); 79 | CASE(WAIT_ON_DE_COUNTER_DIFF); 80 | CASE(SWITCH_BUFFER); 81 | CASE(SET_RESOURCES); 82 | CASE(MAP_PROCESS); 83 | CASE(MAP_QUEUES); 84 | CASE(UNMAP_QUEUES); 85 | CASE(QUERY_STATUS); 86 | CASE(RUN_LIST); 87 | default: 88 | return "???"; 89 | } 90 | #undef CASE 91 | } 92 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/gmc/gmc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * AMD Graphics Memory Controller (GMC). 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | // Forward declarations 19 | class GmcDevice; 20 | 21 | constexpr auto GMC_MMIO_VM = OffsetRange(0x500, 0x78); 22 | constexpr auto GMC_MMIO_MC = OffsetRange(0x800, 0x300); 23 | 24 | class GmcVmSpace : public TranslatorSpace { 25 | friend class GmcDevice; 26 | public: 27 | GmcVmSpace(Space* gmc_mem); 28 | 29 | TranslatorResult translate(Offset off) override; 30 | 31 | private: 32 | U64 base = 0; 33 | }; 34 | 35 | struct GmcDeviceConfig : DeviceConfig { 36 | }; 37 | 38 | class GmcDevice final : public Device { 39 | public: 40 | GmcDevice(Space* mem, const GmcDeviceConfig& config = {}); 41 | 42 | void reset() override; 43 | 44 | U32 mmio_read(U32 index); 45 | void mmio_write(U32 index, U32 value); 46 | 47 | GmcVmSpace& get(U32 vmid); 48 | 49 | private: 50 | std::vector vm_contexts; 51 | U32 vm_invalidate_response; 52 | U32 mc_bist_mismatch_addr; 53 | }; 54 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/liverpool_gc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Liverpool Graphics Controller (GC/Starsha) PCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | 16 | // Engines 17 | #include "gca/gfx.h" 18 | #include "gmc/gmc.h" 19 | #include "oss/ih.h" 20 | #include "sam/sam.h" 21 | #include "smu/smu.h" 22 | 23 | #include 24 | #include 25 | 26 | constexpr auto LIVERPOOL_GC_DEV = 0x1; 27 | constexpr auto LIVERPOOL_GC_FNC = 0x0; 28 | constexpr auto LIVERPOOL_GC_VID = static_cast(0x1002); 29 | constexpr auto LIVERPOOL_GC_DID = static_cast(0x9920); 30 | 31 | struct LiverpoolGCDeviceConfig : PCIeDeviceConfig { 32 | GfxDeviceConfig gfx; 33 | 34 | LiverpoolGCDeviceConfig(PCI_DF df = PCI_DF(LIVERPOOL_GC_DEV, LIVERPOOL_GC_FNC)) 35 | : PCIeDeviceConfig(df, LIVERPOOL_GC_VID, LIVERPOOL_GC_DID, 0x0, PCI_CLASS_DISPLAY_VGA) { 36 | } 37 | }; 38 | 39 | class LiverpoolGCDevice final : public PCIeDevice { 40 | public: 41 | LiverpoolGCDevice(PCIeBus* bus, const LiverpoolGCDeviceConfig& config = {}); 42 | ~LiverpoolGCDevice(); 43 | 44 | // Device interface 45 | void reset() override; 46 | 47 | const auto& get_mmio() const noexcept { 48 | return mmio; 49 | } 50 | 51 | SmuDevice* get_smu() { 52 | return &smu; 53 | } 54 | 55 | private: 56 | MemorySpace* space_bar0; 57 | MemorySpace* space_bar2; 58 | MemorySpace* space_pio; 59 | MemorySpace* space_mmio; 60 | 61 | // State 62 | std::array mmio; 63 | AmdUcode<0x2000> sdma0_ucode; 64 | AmdUcode<0x2000> sdma1_ucode; 65 | 66 | U64 bar0_read(U64 addr, U64 size); 67 | void bar0_write(U64 addr, U64 value, U64 size); 68 | 69 | U64 bar2_read(U64 addr, U64 size); 70 | void bar2_write(U64 addr, U64 value, U64 size); 71 | 72 | U64 pio_read(U64 addr, U64 size); 73 | void pio_write(U64 addr, U64 value, U64 size); 74 | 75 | U64 mmio_read(U64 addr, U64 size); 76 | void mmio_write(U64 addr, U64 value, U64 size); 77 | 78 | // Engines 79 | GmcDevice gmc; 80 | IhDevice ih; 81 | SmuDevice smu; 82 | SamDevice sam; 83 | GfxDevice gfx; 84 | }; 85 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/liverpool_hdac.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Liverpool HD Audio Controller (HDAC) PCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "liverpool_hdac.h" 12 | 13 | enum { 14 | HDAC_UNK08 = 0x08, 15 | /* The following three registers are involved in muting audio */ 16 | HDAC_UNK60 = 0x60, // Command? 17 | HDAC_UNK64 = 0x64, // Size? 18 | HDAC_UNK68 = 0x68, // Flags? 19 | }; 20 | 21 | // During the muting audio phase, following values are passed to HDAC_UNK60 22 | // 377703h 377823h 377943h 377A63h 23 | // 577703h 577823h 577943h 577A63h 24 | // 777703h 777823h 777943h 777A63h 25 | 26 | LiverpoolHDACDevice::LiverpoolHDACDevice(PCIeBus* bus, const LiverpoolHDACDeviceConfig& config) 27 | : PCIeDevice(bus, config) { 28 | // Define BARs 29 | mmio = new MemorySpace(this, 0x4000, { 30 | static_cast(&LiverpoolHDACDevice::mmio_read), 31 | static_cast(&LiverpoolHDACDevice::mmio_write), 32 | }); 33 | 34 | // Register BARs 35 | register_bar(0, PCI_BASE_ADDRESS_SPACE_MEM, mmio); 36 | 37 | reset(); 38 | } 39 | 40 | LiverpoolHDACDevice::~LiverpoolHDACDevice() { 41 | } 42 | 43 | void LiverpoolHDACDevice::reset() { 44 | // PCI Configuration Space 45 | auto& header = config_header(); 46 | header.command = PCI_COMMAND_MEMORY; // TODO: Is this needed? 47 | header.header_type |= PCI_HEADER_TYPE_MULTI_FUNCTION; 48 | header.intr_line = 0xFF; 49 | header.intr_pin = 0x02; 50 | msi_enable(1, true); 51 | } 52 | 53 | U64 LiverpoolHDACDevice::mmio_read(U64 addr, U64 size) { 54 | U64 value = 0; 55 | 56 | switch (addr) { 57 | case HDAC_UNK08: 58 | value = 0; 59 | break; 60 | case HDAC_UNK68: 61 | value = 0; 62 | break; 63 | default: 64 | assert_always("Unimplemented"); 65 | // TODO: Previous implementation was memory-like. 66 | } 67 | return value; 68 | } 69 | 70 | void LiverpoolHDACDevice::mmio_write(U64 addr, U64 value, U64 size) { 71 | switch (addr) { 72 | case HDAC_UNK08: 73 | break; 74 | default: 75 | assert_always("Unimplemented"); 76 | // TODO: Previous implementation was memory-like. 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/liverpool_hdac.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Liverpool HD Audio Controller (HDAC) PCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | enum { 16 | LIVERPOOL_HDAC_DEV = 0x1, 17 | LIVERPOOL_HDAC_FNC = 0x1, 18 | }; 19 | 20 | constexpr auto LIVERPOOL_HDAC_VID = static_cast(0x1002); 21 | constexpr auto LIVERPOOL_HDAC_DID = static_cast(0x9921); 22 | 23 | struct LiverpoolHDACDeviceConfig : PCIeDeviceConfig { 24 | LiverpoolHDACDeviceConfig(PCI_DF df = PCI_DF(LIVERPOOL_HDAC_DEV, LIVERPOOL_HDAC_FNC)) 25 | : PCIeDeviceConfig(df, LIVERPOOL_HDAC_VID, LIVERPOOL_HDAC_DID, 0x0, PCI_CLASS_MULTIMEDIA_AUDIO) { 26 | } 27 | }; 28 | 29 | class LiverpoolHDACDevice final : public PCIeDevice { 30 | public: 31 | LiverpoolHDACDevice(PCIeBus* bus, const LiverpoolHDACDeviceConfig& config = {}); 32 | ~LiverpoolHDACDevice(); 33 | 34 | // Device interface 35 | void reset() override; 36 | 37 | private: 38 | MemorySpace* mmio; 39 | 40 | U64 mmio_read(U64 addr, U64 size); 41 | void mmio_write(U64 addr, U64 value, U64 size); 42 | }; 43 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/liverpool_iommu.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Liverpool IOMMU PCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "liverpool_iommu.h" 12 | 13 | LiverpoolIOMMUDevice::LiverpoolIOMMUDevice(PCIeBus* bus, const LiverpoolIOMMUDeviceConfig& config) 14 | : PCIeDevice(bus, config) { 15 | // Define BARs 16 | mmio = new MemorySpace(this, 0x4000, { 17 | static_cast(&LiverpoolIOMMUDevice::mmio_read), 18 | static_cast(&LiverpoolIOMMUDevice::mmio_write), 19 | }); 20 | 21 | // Register BARs 22 | register_bar(0, PCI_BASE_ADDRESS_SPACE_MEM, mmio); 23 | 24 | reset(); 25 | } 26 | 27 | LiverpoolIOMMUDevice::~LiverpoolIOMMUDevice() { 28 | } 29 | 30 | void LiverpoolIOMMUDevice::reset() { 31 | } 32 | 33 | U64 LiverpoolIOMMUDevice::mmio_read(U64 addr, U64 size) { 34 | U64 value = 0; 35 | assert_always("Unimplemented"); 36 | return value; 37 | } 38 | 39 | void LiverpoolIOMMUDevice::mmio_write(U64 addr, U64 value, U64 size) { 40 | assert_always("Unimplemented"); 41 | } 42 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/liverpool_iommu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Liverpool IOMMU PCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | enum { 16 | LIVERPOOL_IOMMU_DEV = 0x0, 17 | LIVERPOOL_IOMMU_FNC = 0x2, 18 | }; 19 | 20 | constexpr auto LIVERPOOL_IOMMU_DID = static_cast(0x1437); 21 | 22 | struct LiverpoolIOMMUDeviceConfig : PCIeDeviceConfig { 23 | LiverpoolIOMMUDeviceConfig(PCI_DF df = PCI_DF(LIVERPOOL_IOMMU_DEV, LIVERPOOL_IOMMU_FNC)) 24 | : PCIeDeviceConfig(df, PCI_VENDOR_ID_AMD, LIVERPOOL_IOMMU_DID, 0x1, 0x0806) { 25 | } 26 | }; 27 | 28 | class LiverpoolIOMMUDevice final : public PCIeDevice { 29 | public: 30 | LiverpoolIOMMUDevice(PCIeBus* bus, const LiverpoolIOMMUDeviceConfig& config = {}); 31 | ~LiverpoolIOMMUDevice(); 32 | 33 | // Device interface 34 | void reset() override; 35 | 36 | private: 37 | MemorySpace* mmio; 38 | 39 | U64 mmio_read(U64 addr, U64 size); 40 | void mmio_write(U64 addr, U64 value, U64 size); 41 | }; 42 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/liverpool_nb.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Liverpool North Bridge (NB) PCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "liverpool_nb.h" 12 | 13 | LiverpoolNBFnc0Device::LiverpoolNBFnc0Device(PCIeBus* bus, const LiverpoolNBFnc0DeviceConfig& config) 14 | : PCIeDevice(bus, config) { 15 | reset(); 16 | } 17 | 18 | LiverpoolNBFnc0Device::~LiverpoolNBFnc0Device() { 19 | } 20 | 21 | void LiverpoolNBFnc0Device::reset() { 22 | } 23 | 24 | LiverpoolNBFnc1Device::LiverpoolNBFnc1Device(PCIeBus* bus, const LiverpoolNBFnc1DeviceConfig& config) 25 | : PCIeDevice(bus, config) { 26 | reset(); 27 | } 28 | 29 | LiverpoolNBFnc1Device::~LiverpoolNBFnc1Device() { 30 | } 31 | 32 | void LiverpoolNBFnc1Device::reset() { 33 | } 34 | 35 | LiverpoolNBFnc2Device::LiverpoolNBFnc2Device(PCIeBus* bus, const LiverpoolNBFnc2DeviceConfig& config) 36 | : PCIeDevice(bus, config) { 37 | reset(); 38 | } 39 | 40 | LiverpoolNBFnc2Device::~LiverpoolNBFnc2Device() { 41 | } 42 | 43 | void LiverpoolNBFnc2Device::reset() { 44 | } 45 | 46 | LiverpoolNBFnc3Device::LiverpoolNBFnc3Device(PCIeBus* bus, const LiverpoolNBFnc3DeviceConfig& config) 47 | : PCIeDevice(bus, config) { 48 | reset(); 49 | } 50 | 51 | LiverpoolNBFnc3Device::~LiverpoolNBFnc3Device() { 52 | } 53 | 54 | void LiverpoolNBFnc3Device::reset() { 55 | /** 56 | * Set APU chipset version. 57 | * Liverpool: 58 | * - 0x00710F00 : LVP A0 59 | * - 0x00710F10 : LVP B0 60 | * - 0x00710F11 : LVP B1 61 | * - 0x00710F12 : LVP B2 62 | * - 0x00710F13 : LVP B2.1 63 | * - 0x00710F30 : LVP+ A0 64 | * - 0x00710F31 : LVP+ A0b 65 | * - 0x00710F32 : LVP+ A1 66 | * - 0x00710F40 : LVP+ B0 67 | * - 0x00710F80 : LVP2 A0 68 | * - 0x00710F81 : LVP2 A1 69 | * - 0x00710FA0 : LVP2C A0 70 | * Gladius: 71 | * - 0x00740F00 : GL A0 72 | * - 0x00740F01 : GL A1 73 | * - 0x00740F10 : GL B0 74 | * - 0x00740F11 : GL B1 75 | * - 0x00740F12 : GL T(B2) 76 | */ 77 | constexpr U32 REG_NB_CPUID_3XFC = 0xFC; 78 | (U32&)config_data[REG_NB_CPUID_3XFC] = 0x00710F13; 79 | } 80 | 81 | LiverpoolNBFnc4Device::LiverpoolNBFnc4Device(PCIeBus* bus, const LiverpoolNBFnc4DeviceConfig& config) 82 | : PCIeDevice(bus, config) { 83 | reset(); 84 | } 85 | 86 | LiverpoolNBFnc4Device::~LiverpoolNBFnc4Device() { 87 | } 88 | 89 | void LiverpoolNBFnc4Device::reset() { 90 | } 91 | 92 | LiverpoolNBFnc5Device::LiverpoolNBFnc5Device(PCIeBus* bus, const LiverpoolNBFnc5DeviceConfig& config) 93 | : PCIeDevice(bus, config) { 94 | reset(); 95 | } 96 | 97 | LiverpoolNBFnc5Device::~LiverpoolNBFnc5Device() { 98 | } 99 | 100 | void LiverpoolNBFnc5Device::reset() { 101 | } 102 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/liverpool_rc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Liverpool Root Complex (RC) PCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "liverpool_rc.h" 12 | #include 13 | 14 | constexpr U32 D0F0xB8 = 0xB8; 15 | constexpr U32 D0F0xBC = 0xBC; 16 | 17 | LiverpoolRCDevice::LiverpoolRCDevice(PCIeBus* bus, const LiverpoolRCDeviceConfig& config) 18 | : PCIeDevice(bus, config) { 19 | reset(); 20 | } 21 | 22 | LiverpoolRCDevice::~LiverpoolRCDevice() { 23 | } 24 | 25 | void LiverpoolRCDevice::reset() { 26 | auto& header = config_header(); 27 | header.header_type |= PCI_HEADER_TYPE_MULTI_FUNCTION; 28 | 29 | // Add PCIe capability 30 | // TODO: Refactor this code 31 | const auto cap_off = add_capability(PCI_CAP_ID_EXP, 0x14 /* V1 */); 32 | (U16&)config_data[cap_off + 2 /*PCI_EXP_FLAGS*/ ] = 0x0001; 33 | (U32&)config_data[cap_off + 4 /*PCI_EXP_DEVCAP*/] = 0; 34 | (U16&)config_data[cap_off + 8 /*PCI_EXP_DEVCTL*/] = 0; 35 | (U16&)config_data[cap_off + 10 /*PCI_EXP_DEVSTA*/] = 0; 36 | (U32&)config_data[cap_off + 12 /*PCI_EXP_LNKCAP*/] = 0; 37 | (U16&)config_data[cap_off + 16 /*PCI_EXP_LNKCTL*/] = 0; 38 | (U16&)config_data[cap_off + 18 /*PCI_EXP_LNKSTA*/] = 0; 39 | 40 | (U32&)config_data[0xE4] = 0xFF; 41 | (U32&)config_mask[0xE4] = ~0xFF; 42 | } 43 | 44 | void LiverpoolRCDevice::config_write(U32 offset, U64 value, size_t size) { 45 | U32 smc_ix; 46 | switch (offset) { 47 | case D0F0xBC: 48 | assert(size == 4); 49 | smc_ix = (U32&)config_data[D0F0xB8]; 50 | smu->smc_write(smc_ix, value); 51 | break; 52 | default: 53 | PCIDevice::config_write(offset, value, size); 54 | } 55 | } 56 | 57 | U64 LiverpoolRCDevice::config_read(U32 offset, size_t size) { 58 | U64 value = 0; 59 | 60 | U32 smc_ix; 61 | switch (offset) { 62 | case D0F0xBC: 63 | assert(size == 4); 64 | smc_ix = (U32&)config_data[D0F0xB8]; 65 | value = smu->smc_read(smc_ix); 66 | break; 67 | default: 68 | value = PCIDevice::config_read(offset, size); 69 | } 70 | 71 | return value; 72 | } 73 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/liverpool_rc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Liverpool Root Complex (RC) PCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | // Forward declarations 16 | class SmuDevice; 17 | 18 | enum { 19 | LIVERPOOL_RC_DEV = 0x0, 20 | LIVERPOOL_RC_FNC = 0x0, 21 | }; 22 | 23 | constexpr auto LIVERPOOL_RC_DID = static_cast(0x1436); 24 | 25 | struct LiverpoolRCDeviceConfig : PCIeDeviceConfig { 26 | LiverpoolRCDeviceConfig(PCI_DF df = PCI_DF(LIVERPOOL_RC_DEV, LIVERPOOL_RC_FNC)) 27 | : PCIeDeviceConfig(df, PCI_VENDOR_ID_AMD, LIVERPOOL_RC_DID, 0x1, PCI_CLASS_BRIDGE_HOST) { 28 | } 29 | }; 30 | 31 | class LiverpoolRCDevice final : public PCIeDevice { 32 | public: 33 | LiverpoolRCDevice(PCIeBus* bus, const LiverpoolRCDeviceConfig& config = {}); 34 | ~LiverpoolRCDevice(); 35 | 36 | // Device interface 37 | void reset() override; 38 | 39 | void config_write(U32 offset, U64 value, size_t size) override; 40 | U64 config_read(U32 offset, size_t size) override; 41 | 42 | void set_smu(SmuDevice* smu) { 43 | this->smu = smu; 44 | } 45 | 46 | private: 47 | SmuDevice* smu; 48 | 49 | U32 smc_ix; 50 | }; 51 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/liverpool_rp.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Liverpool Root Port (RP) PCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "liverpool_rp.h" 12 | 13 | LiverpoolRPDevice::LiverpoolRPDevice(PCIeBus* bus, const LiverpoolRPDeviceConfig& config) 14 | : PCIeDevice(bus, config) { 15 | reset(); 16 | } 17 | 18 | LiverpoolRPDevice::~LiverpoolRPDevice() { 19 | } 20 | 21 | void LiverpoolRPDevice::reset() { 22 | } 23 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/liverpool_rp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Liverpool Root Port (RP) PCI device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | enum { 16 | LIVERPOOL_RP_DEV = 0x2, 17 | LIVERPOOL_RP_FNC = 0x0, 18 | }; 19 | 20 | constexpr auto LIVERPOOL_RP_DID = static_cast(0x1438); 21 | 22 | struct LiverpoolRPDeviceConfig : PCIeDeviceConfig { 23 | LiverpoolRPDeviceConfig(PCI_DF df = PCI_DF(LIVERPOOL_RP_DEV, LIVERPOOL_RP_FNC)) 24 | : PCIeDeviceConfig(df, PCI_VENDOR_ID_AMD, LIVERPOOL_RP_DID, 0x1, PCI_CLASS_BRIDGE_HOST) { 25 | } 26 | }; 27 | 28 | class LiverpoolRPDevice final : public PCIeDevice { 29 | public: 30 | LiverpoolRPDevice(PCIeBus* bus, const LiverpoolRPDeviceConfig& config = {}); 31 | ~LiverpoolRPDevice(); 32 | 33 | // Device interface 34 | void reset() override; 35 | }; 36 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/oss/ih.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * AMD Interrupt Handler (IH) device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "ih.h" 12 | #include 13 | 14 | #include "oss_2_0_d.h" 15 | #include "oss_2_0_sh_mask.h" 16 | 17 | IhDevice::IhDevice(PCIeDevice& gc, GmcDevice& gmc) 18 | : Device(nullptr), gc(gc), gmc(gmc) { 19 | reset(); 20 | } 21 | 22 | void IhDevice::reset() { 23 | // TODO: Do we actually need to zero-initialize anything? Non-status registers might just be undefined. 24 | memset(vmid_lut, 0, sizeof(vmid_lut)); 25 | rb_cntl = 0; 26 | rb_base = 0; 27 | rb_rptr = 0; 28 | rb_wptr = 0; 29 | rb_wptr_addr = 0; 30 | 31 | cntl = 0; 32 | level_status = 0; 33 | status = 0; 34 | status_idle = true; 35 | status_input_idle = true; 36 | status_rb_idle = true; 37 | 38 | perfmon_cntl = 0; 39 | perfcounter0_result = 0; 40 | perfcounter1_result = 0; 41 | advfault_cntl = 0; 42 | } 43 | 44 | U32 IhDevice::mmio_read(U32 index) { 45 | U32 value = 0; 46 | 47 | switch (index) { 48 | case mmIH_RB_BASE: 49 | value = rb_base; 50 | break; 51 | case mmIH_RB_WPTR: 52 | value = rb_wptr; 53 | break; 54 | case mmIH_RB_WPTR_ADDR_LO: 55 | value = rb_wptr_addr_lo; 56 | break; 57 | case mmIH_RB_WPTR_ADDR_HI: 58 | value = rb_wptr_addr_hi; 59 | break; 60 | case mmIH_STATUS: 61 | value = status; 62 | break; 63 | default: 64 | assert_always("Unimplemented"); 65 | } 66 | 67 | return value; 68 | } 69 | 70 | void IhDevice::mmio_write(U32 index, U32 value) { 71 | switch (index) { 72 | case mmIH_RB_CNTL: 73 | rb_cntl = value; 74 | break; 75 | case mmIH_RB_BASE: 76 | rb_base = value; 77 | break; 78 | case mmIH_RB_WPTR: 79 | rb_wptr = value; 80 | break; 81 | case mmIH_RB_WPTR_ADDR_LO: 82 | rb_wptr_addr_lo = value; 83 | break; 84 | case mmIH_RB_WPTR_ADDR_HI: 85 | rb_wptr_addr_hi = value; 86 | break; 87 | default: 88 | assert_always("Unimplemented"); 89 | } 90 | } 91 | 92 | void IhDevice::push_iv(U32 vmid, U32 src_id, U32 src_data) { 93 | const U08 ringid = 0; // TODO 94 | const U16 pasid = 0; // TODO 95 | assert(vmid < 16); 96 | assert(src_id < 0x100); 97 | assert(src_data < 0x10000000); 98 | 99 | std::unique_lock lock(mutex); 100 | rb_push(src_id); 101 | rb_push(src_data); 102 | rb_push(((pasid << 16) | (vmid << 8) | ringid)); 103 | rb_push(0 /* TODO: timestamp & 0xFFFFFFF */); 104 | lock.unlock(); 105 | 106 | if (gc.msi_ready()) { 107 | gc.msi_notify(0); 108 | } 109 | } 110 | 111 | void IhDevice::rb_push(U32 value) { 112 | auto& vm = static_cast(gmc.get(mc_vmid)); 113 | uint64_t addr; 114 | 115 | // Push value 116 | addr = ((U64)rb_base << 8) + rb_wptr; 117 | vm.write(addr, value); 118 | rb_wptr += 4; 119 | rb_wptr &= rb_size() - 1; 120 | 121 | // Update WPTR 122 | vm.write(rb_wptr_addr, rb_wptr); 123 | } 124 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/sam/ccp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * AMD Cryptographic Co-Processor (CCP) device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | enum CcpOp { 16 | CCP_OP_AES = 0, 17 | CCP_OP_AES_INSITU = 1, 18 | CCP_OP_XTS = 2, 19 | CCP_OP_SHA = 3, 20 | CCP_OP_RSA = 4, 21 | CCP_OP_PASS = 5, 22 | CCP_OP_ECC = 6, 23 | CCP_OP_ZLIB = 7, 24 | CCP_OP_TRNG = 8, 25 | CCP_OP_HMAC = 9, 26 | CCP_OP_SNVS = 10, 27 | }; 28 | 29 | enum CcpAesSize { 30 | CCP_AES_SIZE_128 = 0, 31 | CCP_AES_SIZE_192 = 1, 32 | CCP_AES_SIZE_256 = 2, 33 | }; 34 | 35 | enum CcpAesMode { 36 | CCP_AES_MODE_DEC = 0, 37 | CCP_AES_MODE_ENC = 1, 38 | }; 39 | 40 | enum CcpAesMode { 41 | CCP_AES_MODE_ECB = 0, 42 | }; 43 | 44 | #define CCP_FLAG_SLOT_KEY 0x40000 45 | #define CCP_FLAG_SLOT_OUT 0x80000 46 | 47 | #define CCP_OP_AES_KEY(M) M(11,10) 48 | #define CCP_OP_AES_TYPE(M) M(12,12) 49 | #define CCP_OP_AES_MODE(M) M(15,13) 50 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/sam/sam.h: -------------------------------------------------------------------------------- 1 | /** 2 | * AMD Secure Asset Management Unit (SAMU) device. 3 | * 4 | * Based on research from: Alexey Kulaev (@flatz). 5 | * 6 | * Copyright 2017-2021. Orbital project. 7 | * Released under MIT license. Read LICENSE for more details. 8 | * 9 | * Authors: 10 | * - Alexandro Sanchez Bach 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | // Forward declarations 19 | class GmcDevice; 20 | class IhDevice; 21 | class SmuDevice; 22 | 23 | constexpr auto SAM_MMIO = OffsetRange(0x8800, 0x100); 24 | constexpr auto SAM0_MMIO = OffsetRange(0x8800, 0x100); 25 | constexpr auto SAM1_MMIO = OffsetRange(0x8900, 0x100); 26 | 27 | /* SAMU Commands */ 28 | struct samu_command_io_open_t { 29 | char name[8]; 30 | }; 31 | 32 | struct samu_command_io_close_t { 33 | LE fd; 34 | }; 35 | 36 | struct samu_command_io_read_t { 37 | LE fd; 38 | LE size; 39 | LE data[0]; 40 | }; 41 | 42 | struct samu_command_io_write_t { 43 | LE fd; 44 | LE size; 45 | LE data[0]; 46 | }; 47 | 48 | struct samu_command_io_seek_t { 49 | LE fd; 50 | LE offset; 51 | }; 52 | 53 | struct samu_command_service_spawn_t { 54 | char name[16]; 55 | LE args[4]; 56 | }; 57 | 58 | struct samu_command_service_ccp_t { 59 | LE opcode; 60 | LE status; 61 | 62 | union { 63 | struct { 64 | LE data_size; 65 | LE in_addr; 66 | LE out_addr; 67 | LE key[0x20]; 68 | LE iv[0x10]; 69 | } aes; 70 | 71 | struct { 72 | LE num_sectors; 73 | LE in_addr; 74 | LE out_addr; 75 | LE start_sector; 76 | LE key[0x20]; 77 | } xts; 78 | 79 | struct { 80 | LE data_size; 81 | LE in_addr; 82 | LE out_addr; 83 | LE hash[0x20]; 84 | } sha; 85 | 86 | struct { 87 | LE data_size; 88 | LE data_addr; 89 | LE data_size_bits; 90 | LE hash[0x20]; 91 | LE key[0x40]; 92 | LE key_size; 93 | } hmac; 94 | 95 | struct { 96 | LE data[0x20]; 97 | } rng; 98 | 99 | struct { 100 | LE unk_08; 101 | LE in_size; 102 | LE out_size; 103 | LE unk_14; 104 | LE in_addr; 105 | LE out_addr; 106 | } zlib; 107 | }; 108 | }; 109 | 110 | struct samu_command_service_rand_t { 111 | LE data[0x10]; 112 | }; 113 | 114 | class SamDevice : public Device { 115 | public: 116 | SamDevice(GmcDevice& gmc, IhDevice& ih, SmuDevice& smu); 117 | 118 | void reset(); 119 | 120 | U32 mmio_read(U32 index); 121 | void mmio_write(U32 index, U32 value); 122 | 123 | private: 124 | GmcDevice& gmc; 125 | IhDevice& ih; 126 | SmuDevice& smu; 127 | 128 | std::array gpr; 129 | std::array ix_data; 130 | std::array sab_ix_data; 131 | U32 ix_index; 132 | U32 sab_ix_index; 133 | 134 | U32 ih_cpu_am32_int_status; 135 | U32 ih_am32_cpu_int_status; 136 | union { 137 | LE ih_cpu_am32_int_ctx; 138 | Bitfield ih_cpu_am32_int_flags; 139 | struct { 140 | LE ih_cpu_am32_int_ctx_low; 141 | LE ih_cpu_am32_int_ctx_high; 142 | }; 143 | }; 144 | union { 145 | LE ih_am32_cpu_int_ctx; 146 | struct { 147 | LE ih_am32_cpu_int_ctx_low; 148 | LE ih_am32_cpu_int_ctx_high; 149 | }; 150 | }; 151 | 152 | void handle_request(U32 value); 153 | }; 154 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/sam/sam_regs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * AMD Secure Asset Management Unit (SAMU) device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | // SAM block 14 | #define mmSAM_IX_INDEX 0x8800 15 | #define mmSAM_IX_DATA 0x8801 16 | #define mmSAM_SAB_IX_INDEX 0x8802 17 | #define mmSAM_SAB_IX_DATA 0x8803 18 | #define mmSAM_IND_INDEX 0x8800 19 | #define mmSAM_IND_DATA 0x8801 20 | #define mmSAM_AM32_BOOT_BASE 0x8809 21 | #define mmSAM_AM32_BOOT_OFFSET 0x880A 22 | #define mmSAM_AM32_BOOT_LENGTH 0x880B 23 | #define mmSAM_AM32_BOOT_CTRL 0x880C 24 | #define mmSAM_AM32_BOOT_STATUS 0x880D 25 | #define mmSAM_AM32_BOOT_HASH0 0x880E 26 | #define mmSAM_AM32_BOOT_HASH1 0x880F 27 | #define mmSAM_AM32_BOOT_HASH2 0x8810 28 | #define mmSAM_AM32_BOOT_HASH3 0x8811 29 | #define mmSAM_AM32_BOOT_HASH4 0x8812 30 | #define mmSAM_AM32_BOOT_HASH5 0x8813 31 | #define mmSAM_AM32_BOOT_HASH6 0x8814 32 | #define mmSAM_AM32_BOOT_HASH7 0x8815 33 | #define mmSAM_EMU_SRCID 0x8816 34 | #define mmSAM_GPR_SCRATCH_4 0x8818 35 | #define mmSAM_GPR_SCRATCH_5 0x8819 36 | #define mmSAM_GPR_SCRATCH_6 0x881A 37 | #define mmSAM_GPR_SCRATCH_7 0x881B 38 | #define mmSAM_GPR_SCRATCH_0 0x881C 39 | #define mmSAM_GPR_SCRATCH_1 0x881D 40 | #define mmSAM_GPR_SCRATCH_2 0x881E 41 | #define mmSAM_GPR_SCRATCH_3 0x881F 42 | #define mmSAM_POWER_GATE 0x8834 43 | #define mmSAM_BOOT_PWR_UP 0x8835 44 | #define mmSAM_SMU_ALLOW_MEM_ACCESS 0x8836 45 | #define mmSAM_PGFSM_CONFIG_REG 0x8837 46 | #define mmSAM_PGFSM_WRITE_REG 0x8838 47 | #define mmSAM_PGFSM_READ_REG 0x8839 48 | #define mmSAM_PKI_FAIL_STATUS 0x883A 49 | 50 | // SAMIND block 51 | #define ixSAM_RST_HOST_SOFT_RESET 0x0001 52 | #define ixSAM_CGC_HOST_CTRL 0x0003 53 | #define ixSAM_IH_CPU_AM32_INT 0x0032 54 | #define ixSAM_IH_CPU_AM32_INT_CTX_HIGH 0x0033 55 | #define ixSAM_IH_CPU_AM32_INT_CTX_LOW 0x0034 56 | #define ixSAM_IH_AM32_CPU_INT_CTX_HIGH 0x0035 57 | #define ixSAM_IH_AM32_CPU_INT_CTX_LOW 0x0036 58 | #define ixSAM_IH_AM32_CPU_INT_ACK 0x0037 59 | #define ixSAM_SCRATCH_0 0x0038 60 | #define ixSAM_SCRATCH_1 0x0039 61 | #define ixSAM_SCRATCH_2 0x003A 62 | #define ixSAM_SCRATCH_3 0x003B 63 | #define ixSAM_SCRATCH_4 0x003C 64 | #define ixSAM_SCRATCH_5 0x003D 65 | #define ixSAM_SCRATCH_6 0x003E 66 | #define ixSAM_SCRATCH_7 0x003F 67 | #define ixSAM_IH_CPU_AM32_INT_STATUS 0x004A 68 | #define ixSAM_IH_AM32_CPU_INT_STATUS 0x004B 69 | #define ixSAM_RST_HOST_SOFT_RST_RDY 0x0051 70 | 71 | // SABIND block 72 | #define ixSAM_SAB_INIT_TLB_CONFIG 0x0004 73 | #define ixSAM_SAB_EFUSE_STATUS_CNTL 0x0029 74 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool/smu/smu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * AMD System Management Unit (SMU) device. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | 16 | // Forward declarations 17 | class GmcDevice; 18 | class IhDevice; 19 | 20 | constexpr auto SMU_MMIO = OffsetRange(0x80, 0x40); 21 | 22 | class SmuDevice : public Device { 23 | public: 24 | SmuDevice(GmcDevice& gmc, IhDevice& ih); 25 | 26 | void reset(); 27 | 28 | U32 mmio_read(U32 index); 29 | void mmio_write(U32 index, U32 value); 30 | 31 | U32 smc_read(U32 index); 32 | void smc_write(U32 index, U32 value); 33 | 34 | private: 35 | GmcDevice& gmc; 36 | IhDevice& ih; 37 | 38 | U32 smc_ix; 39 | 40 | // IOC 41 | U32 ioc_arg; 42 | 43 | void update_ioc(U32 req); 44 | }; 45 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool_pci.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Liverpool PCI Host/Bus devices. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "liverpool_pci.h" 12 | 13 | // Liverpool Bus 14 | LiverpoolBus::LiverpoolBus(Device* parent, IOAPICDevice* ioapic, const PCIeBusConfig& config) 15 | : PCIeBus(parent, config), ioapic(ioapic) {} 16 | 17 | LiverpoolBus::~LiverpoolBus() {} 18 | 19 | void LiverpoolBus::set_irq(void* opaque, int pirq, int level) { 20 | const int gsi = pirq + 16; // TODO 21 | 22 | auto* irq = ioapic->irq(gsi); 23 | irq->set(level); 24 | } 25 | 26 | int LiverpoolBus::map_irq(PCI_DF df, int intx) { 27 | int pirq = ((df.d + intx) % 4) + 4; // TODO 28 | return 0; 29 | } 30 | 31 | void LiverpoolBus::route_irq(PCIDevice* opaque, int pin) { 32 | assert_always("Unimplemented"); 33 | } 34 | 35 | // Liverpool Host 36 | LiverpoolHost::LiverpoolHost(Device* parent, IOAPICDevice* ioapic, const PCIeHostConfig& config) 37 | : PCIeHost(parent, config) { 38 | // Create PCIe bus 39 | _bus = new LiverpoolBus(this, ioapic); 40 | 41 | // Create PCI IO ports 42 | const MemorySpaceOps config_data_ops = { 43 | static_cast(&LiverpoolHost::config_read), 44 | static_cast(&LiverpoolHost::config_write), 45 | }; 46 | ContainerSpace* io = _machine->io(); 47 | config_addr_io = new MemorySpace(this, 0x4); 48 | config_data_io = new MemorySpace(this, 0x4, config_data_ops); 49 | io->addSubspace(config_addr_io, PCI_HOST_CONFIG_ADDR); 50 | io->addSubspace(config_data_io, PCI_HOST_CONFIG_DATA); 51 | } 52 | 53 | LiverpoolHost::~LiverpoolHost() {} 54 | -------------------------------------------------------------------------------- /src/orbital/hardware/liverpool_pci.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Liverpool PCI Host/Bus devices. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | // Liverpool PCI Bus 16 | class LiverpoolBus : public PCIeBus { 17 | public: 18 | LiverpoolBus(Device* parent, IOAPICDevice* ioapic, const PCIeBusConfig& config = {}); 19 | ~LiverpoolBus(); 20 | 21 | void set_irq(void* opaque, int irq, int level) override; 22 | int map_irq(PCI_DF df, int irq) override; 23 | void route_irq(PCIDevice* opaque, int pin) override; 24 | 25 | private: 26 | IOAPICDevice* ioapic; 27 | }; 28 | 29 | // Liverpool PCI Host 30 | class LiverpoolHost final : public PCIeHost { 31 | public: 32 | LiverpoolHost(Device* parent, IOAPICDevice* ioapic, const PCIeHostConfig& config = {}); 33 | ~LiverpoolHost(); 34 | 35 | LiverpoolBus* bus() { 36 | return static_cast(_bus); 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /src/orbital/hardware/ps4.h: -------------------------------------------------------------------------------- 1 | /** 2 | * PlayStation 4 machine. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | #include 16 | 17 | // Forward declarations 18 | class AeoliaACPIDevice; 19 | class AeoliaAHCIDevice; 20 | class AeoliaDMACDevice; 21 | class AeoliaGBEDevice; 22 | class AeoliaMemDevice; 23 | class AeoliaPCIeDevice; 24 | class AeoliaSDHCIDevice; 25 | class AeoliaXHCIDevice; 26 | class LiverpoolHost; 27 | class LiverpoolRCDevice; 28 | class LiverpoolGCDevice; 29 | class LiverpoolHDACDevice; 30 | class LiverpoolIOMMUDevice; 31 | class LiverpoolRPDevice; 32 | class LiverpoolNBFnc0Device; 33 | class LiverpoolNBFnc1Device; 34 | class LiverpoolNBFnc2Device; 35 | class LiverpoolNBFnc3Device; 36 | class LiverpoolNBFnc4Device; 37 | class LiverpoolNBFnc5Device; 38 | class VulkanManager; 39 | 40 | struct PS4MachineConfig : MachineConfig { 41 | CharHost* aeolia_uart0 = nullptr; 42 | CharHost* aeolia_uart1 = nullptr; 43 | VulkanManager* vk = nullptr; 44 | 45 | PS4MachineConfig(); 46 | }; 47 | 48 | class PS4Machine : public Machine { 49 | public: 50 | PS4Machine(const PS4MachineConfig& config = {}); 51 | ~PS4Machine(); 52 | 53 | /** 54 | * Reset the console and boot normally into the installed OrbisOS. 55 | */ 56 | void boot(); 57 | 58 | /** 59 | * Reset the console and boot into safe mode of the installed OrbisOS. 60 | * From there one can (re)install all OrbisOS contents in the virtual HDD 61 | * given a virtual USB storage device containing a recovery PUP. 62 | */ 63 | void recover(); 64 | 65 | /** 66 | * Begin recovery process by booting into safe mode from a PUP-contained kernel. 67 | * From there one can (re)install all OrbisOS contents in the virtual HDD. 68 | * The virtual USB storage device will be automatically created. 69 | * @param[in] pup Path to recovery PUP file 70 | */ 71 | void recover(std::filesystem::path pup); 72 | 73 | // Hardware 74 | 75 | /** 76 | * Get constant reference to the Graphics Controller (e.g. used for debugging). 77 | */ 78 | const LiverpoolGCDevice& gc() const noexcept { 79 | return *lvp_gc; 80 | } 81 | 82 | private: 83 | MemorySpace* space_ubios; 84 | MemorySpace* space_ram; 85 | AliasSpace* space_ram_below_4g; 86 | AliasSpace* space_ram_above_4g; 87 | 88 | // Liverpool 89 | std::vector cpus; 90 | IOAPICDevice* ioapic; 91 | LiverpoolHost* lvp_host; 92 | LiverpoolRCDevice* lvp_rc; 93 | LiverpoolGCDevice* lvp_gc; 94 | LiverpoolHDACDevice* lvp_hdac; 95 | LiverpoolIOMMUDevice* lvp_iommu; 96 | LiverpoolRPDevice* lvp_rp; 97 | 98 | LiverpoolNBFnc0Device* lvp_fnc0; 99 | LiverpoolNBFnc1Device* lvp_fnc1; 100 | LiverpoolNBFnc2Device* lvp_fnc2; 101 | LiverpoolNBFnc3Device* lvp_fnc3; 102 | LiverpoolNBFnc4Device* lvp_fnc4; 103 | LiverpoolNBFnc5Device* lvp_fnc5; 104 | 105 | // Aeolia 106 | AeoliaACPIDevice* aeolia_acpi; 107 | AeoliaGBEDevice* aeolia_gbe; 108 | AeoliaAHCIDevice* aeolia_ahci; 109 | AeoliaSDHCIDevice* aeolia_sdhci; 110 | AeoliaPCIeDevice* aeolia_pcie; 111 | AeoliaDMACDevice* aeolia_dmac; 112 | AeoliaMemDevice* aeolia_mem; 113 | AeoliaXHCIDevice* aeolia_xhci; 114 | }; 115 | -------------------------------------------------------------------------------- /src/orbital/host/graphics/vulkan.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Vulkan graphics backend. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | enum VulkanManagerMode { 22 | VULKAN_MANAGER_CREATE, 23 | VULKAN_MANAGER_REUSE, 24 | }; 25 | 26 | struct VulkanManagerConfig { 27 | // Reusing 28 | VkInstance instance = VK_NULL_HANDLE; 29 | VkDevice device = VK_NULL_HANDLE; 30 | 31 | // Creating 32 | bool debug; 33 | std::set i_exts; 34 | std::set i_layers; 35 | std::set d_exts; 36 | std::set d_layers; 37 | }; 38 | 39 | class VulkanManager { 40 | public: 41 | VulkanManager(const VulkanManagerConfig& config = {}); 42 | ~VulkanManager(); 43 | 44 | VkInstance getInstance() const { 45 | return instance; 46 | } 47 | VkPhysicalDevice getPhysicalDevice() const { 48 | return pdev; 49 | } 50 | VkDevice getDevice() const { 51 | return device; 52 | } 53 | uint32_t getQueueFamilyIndex() const { 54 | return queueFamilyIndex; 55 | } 56 | VkQueue getQueue() const { 57 | return queue; 58 | } 59 | 60 | /** 61 | * Create Vulkan instance. 62 | */ 63 | void init_instance(std::set exts, std::set layers, bool debug); 64 | 65 | /** 66 | * Create Vulkan device. 67 | */ 68 | void init_device(std::set exts, std::set layers, VkSurfaceKHR surface); 69 | 70 | private: 71 | VkInstance instance; 72 | VkDebugUtilsMessengerEXT debug_messenger; 73 | 74 | VkPhysicalDevice pdev; 75 | VkDevice device; 76 | uint32_t queueFamilyIndex; 77 | VkQueue queue; 78 | 79 | // Helpers 80 | 81 | /** 82 | * Find suitable queue for graphics commands. 83 | */ 84 | uint32_t find_queue_graphics(const std::vector& qprops, VkSurfaceKHR surface); 85 | }; 86 | 87 | static inline void vk_assert(VkResult res, const std::source_location location = std::source_location::current()) { 88 | if (res != VK_SUCCESS) { 89 | std::cerr << "Error: " 90 | << location.file_name() << "(" 91 | << location.line() << ":" 92 | << location.column() << ") `" 93 | << location.function_name() << "`: " 94 | << "Failed!" << std::endl; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/orbital/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Orbital entry point. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | int main(int argc, char** argv) { 17 | UI ui{}; 18 | 19 | PS4MachineConfig config = {}; 20 | config.aeolia_uart0 = ui.get_uart0_backend(); 21 | config.aeolia_uart1 = ui.get_uart1_backend(); 22 | config.vk = ui.get_vk(); 23 | 24 | PS4Machine ps4(config); 25 | ps4.recover("pups/PS4UPDATE.PUP"); 26 | ps4.resume(); 27 | 28 | 29 | ui.task(ps4); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /src/orbital/offset_range.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Offset range helper. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | struct OffsetRange { 14 | uint64_t base; 15 | uint64_t size; 16 | 17 | constexpr OffsetRange(uint64_t base, uint64_t size) 18 | : base(base), size(size) { 19 | } 20 | constexpr bool contains(uint64_t off) const noexcept { 21 | return (base <= off) && (off < base + size); 22 | } 23 | constexpr bool contains_strict(uint64_t off, uint64_t len) const noexcept { 24 | return contains(off) && (off + len <= base + size); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /src/orbital/software/bls.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * BLS format. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "bls.h" 12 | 13 | #include 14 | 15 | constexpr U32 BLS_MAGIC = '2BLS'; 16 | constexpr U64 BLS_BLOCK = 0x200; 17 | 18 | U64 BlsStream::read(U64 size, void* buffer) { 19 | std::unique_lock lock(bls->mtx); 20 | Stream& s = bls->s; 21 | s.seek(base + offset, StreamSeek::Set); 22 | size = std::min(size, this->size - offset); 23 | 24 | U64 nbytes = s.read(size, buffer); 25 | offset += nbytes; 26 | return nbytes; 27 | } 28 | 29 | U64 BlsStream::write(U64 size, const void* buffer) { 30 | throw std::runtime_error("Unsupported method"); 31 | } 32 | 33 | void BlsStream::seek(U64 offset, StreamSeek mode) { 34 | switch (mode) { 35 | case StreamSeek::Set: 36 | this->offset = offset; 37 | break; 38 | case StreamSeek::Cur: 39 | this->offset += offset; 40 | break; 41 | case StreamSeek::End: 42 | this->offset = size - offset; 43 | break; 44 | default: 45 | throw std::runtime_error("Unsupported mode"); 46 | } 47 | } 48 | 49 | U64 BlsStream::tell() const { 50 | return offset; 51 | } 52 | 53 | BlsParser::BlsParser(Stream& s) : s(s) { 54 | // Read and verify BLS header 55 | s.seek(0, StreamSeek::Set); 56 | header = s.read_t(); 57 | assert(header.magic == BLS_MAGIC); 58 | assert(header.version <= 2); 59 | } 60 | 61 | BlsParser::~BlsParser() { 62 | } 63 | 64 | std::vector BlsParser::files() { 65 | std::unique_lock lock(mtx); 66 | std::vector names(header.num_files); 67 | s.seek(sizeof(BlsHeader), StreamSeek::Set); 68 | for (auto& name : names) { 69 | auto entry = s.read_t(); 70 | name = entry.file_name; 71 | } 72 | return names; 73 | } 74 | 75 | BlsStream BlsParser::get(std::string_view name) { 76 | std::unique_lock lock(mtx); 77 | s.seek(sizeof(BlsHeader), StreamSeek::Set); 78 | for (U32 i = 0; i < header.num_files; i++) { 79 | auto entry = s.read_t(); 80 | if (name == entry.file_name) 81 | return BlsStream(this, entry.block_offset * BLS_BLOCK, entry.file_size); 82 | } 83 | throw std::runtime_error("Could not find file within BLS"); 84 | } 85 | 86 | BlsStream BlsParser::get(U32 index) { 87 | std::unique_lock lock(mtx); 88 | s.seek(sizeof(BlsHeader) + sizeof(BlsEntry) * index, StreamSeek::Set); 89 | auto entry = s.read_t(); 90 | return BlsStream(this, entry.block_offset * BLS_BLOCK, entry.file_size); 91 | } 92 | -------------------------------------------------------------------------------- /src/orbital/software/bls.h: -------------------------------------------------------------------------------- 1 | /** 2 | * BLS format. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | // Forward declarations 20 | class BlsParser; 21 | 22 | struct BlsEntry { 23 | LE block_offset; 24 | LE file_size; 25 | LE padding[2]; 26 | char file_name[32]; 27 | }; 28 | 29 | struct BlsHeader { 30 | LE magic; 31 | LE version; 32 | LE flags; 33 | LE num_files; 34 | LE num_blocks; 35 | LE padding[3]; 36 | }; 37 | 38 | class BlsStream : public Stream { 39 | BlsParser* bls; 40 | const U64 base; 41 | const U32 size; 42 | U32 offset; 43 | 44 | public: 45 | BlsStream(BlsParser* bls, U32 base, U32 size) 46 | : bls(bls), base(base), size(size), offset(0) {} 47 | 48 | virtual U64 read(U64 size, void* buffer) override; 49 | virtual U64 write(U64 size, const void* buffer) override; 50 | virtual void seek(U64 offset, StreamSeek mode) override; 51 | virtual U64 tell() const override; 52 | }; 53 | 54 | class BlsParser { 55 | friend BlsStream; 56 | Stream& s; 57 | BlsHeader header; 58 | std::mutex mtx; 59 | 60 | public: 61 | BlsParser(Stream& s); 62 | ~BlsParser(); 63 | 64 | /** 65 | * Return list of file names corresponding to the BLS entries. 66 | * @return Vector of strings of the file names 67 | */ 68 | std::vector files(); 69 | 70 | /** 71 | * Get BLS stream by file name 72 | */ 73 | BlsStream get(std::string_view name); 74 | 75 | /** 76 | * Get BLS stream by index 77 | */ 78 | BlsStream get(U32 index); 79 | }; 80 | -------------------------------------------------------------------------------- /src/orbital/software/cf.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Common Format (CF) format. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "cf.h" 12 | 13 | #include 14 | 15 | void CfParser::decrypt(Buffer& buffer, const CfMeta& meta) { 16 | Botan::SymmetricKey key(meta.data_key, 16); 17 | Botan::InitializationVector iv(meta.data_iv, 16); 18 | auto cipher = Botan::get_cipher("AES-128/CBC/NoPadding", key, iv, Botan::Cipher_Dir::DECRYPTION); 19 | 20 | const auto size_aligned = buffer.size() & ~0xF; 21 | const auto overflow = buffer.size() & 0xF; 22 | U08 prev_block[16]; 23 | U08 next_block[16]; 24 | if (overflow && size_aligned >= 16) { 25 | memcpy(prev_block, &buffer[size_aligned - 16], 16); 26 | } 27 | 28 | Botan::Pipe pipe(cipher); 29 | pipe.start_msg(); 30 | pipe.write(buffer.data(), size_aligned); 31 | pipe.end_msg(); 32 | pipe.read(buffer.data(), size_aligned); 33 | 34 | // Apply custom CTS if unaligned 35 | if (overflow) { 36 | auto cipher_enc = Botan::get_cipher("AES-128/CBC", key, Botan::Cipher_Dir::ENCRYPTION); 37 | Botan::Pipe pipe_enc(cipher_enc); 38 | pipe_enc.start_msg(); 39 | pipe_enc.write(prev_block, 16); 40 | pipe_enc.end_msg(); 41 | pipe_enc.read(next_block, 16); 42 | for (size_t i = 0; i < overflow; i++) { 43 | buffer[size_aligned + i] ^= next_block[i]; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/orbital/software/cf.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Common Format (CF) format. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | struct CfSegment { 16 | enum AttrFlags { 17 | FLAGS_INFO = (1 << 0), 18 | FLAGS_ENCRYPTION = (1 << 1), 19 | FLAGS_SIGNING = (1 << 2), 20 | FLAGS_COMPRESSION = (1 << 3), 21 | FLAGS_BLOCKS = (1 << 11), 22 | FLAGS_DIGESTS = (1 << 16), 23 | FLAGS_EXTENTS = (1 << 17), 24 | }; 25 | 26 | LE attr; 27 | LE offset; 28 | LE mem_size; 29 | LE file_size; 30 | 31 | U64 id() const noexcept { 32 | return attr >> 20; 33 | } 34 | U64 block_size() const noexcept { 35 | if (has_blocks()) { 36 | return UINT64_C(1) << (((attr >> 12) & 0xF) + 12); 37 | } 38 | else { 39 | return 0x10000; 40 | } 41 | } 42 | U64 block_count() const noexcept { 43 | const U64 bs = block_size(); 44 | return (file_size + bs - 1) / bs; 45 | } 46 | 47 | // Helpers 48 | bool is_info() const noexcept { 49 | return attr & FLAGS_INFO; 50 | } 51 | bool is_encrypted() const noexcept { 52 | return attr & FLAGS_ENCRYPTION; 53 | } 54 | bool is_signed() const noexcept { 55 | return attr & FLAGS_SIGNING; 56 | } 57 | bool is_compressed() const noexcept { 58 | return attr & FLAGS_COMPRESSION; 59 | } 60 | bool has_blocks() const noexcept { 61 | return attr & FLAGS_BLOCKS; 62 | } 63 | bool has_digests() const noexcept { 64 | return attr & FLAGS_DIGESTS; 65 | } 66 | bool has_extents() const noexcept { 67 | return attr & FLAGS_EXTENTS; 68 | } 69 | }; 70 | 71 | struct CfMeta { 72 | U08 data_key[16]; 73 | U08 data_iv[16]; 74 | U08 digest[32]; 75 | U08 digest_key[16]; 76 | }; 77 | 78 | class CfParser { 79 | protected: 80 | Stream& s; 81 | 82 | public: 83 | CfParser(Stream& s) : s(s) {} 84 | 85 | static void decrypt(Buffer& data, const CfMeta& meta); 86 | }; 87 | -------------------------------------------------------------------------------- /src/orbital/software/elf.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * ELF format. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "elf.h" 12 | 13 | ElfParser::ElfParser(Stream& s) : s(s) { 14 | ehdr_offset = s.tell(); 15 | U08 e_ident[EI_NIDENT] = {}; 16 | s.read(EI_NIDENT, &e_ident); 17 | assert(e_ident[EI_MAG0] == '\x7F'); 18 | assert(e_ident[EI_MAG1] == 'E'); 19 | assert(e_ident[EI_MAG2] == 'L'); 20 | assert(e_ident[EI_MAG3] == 'F'); 21 | 22 | // Determine ELF-type at runtime 23 | switch (e_ident[EI_CLASS]) { 24 | case ELFCLASS32: 25 | switch (e_ident[EI_DATA]) { 26 | case ELFDATA2LSB: 27 | type = ElfType::LE_32; 28 | break; 29 | case ELFDATA2MSB: 30 | type = ElfType::BE_32; 31 | break; 32 | default: 33 | throw std::runtime_error("Unimplemented"); 34 | } 35 | break; 36 | case ELFCLASS64: 37 | switch (e_ident[EI_DATA]) { 38 | case ELFDATA2LSB: 39 | type = ElfType::LE_64; 40 | break; 41 | case ELFDATA2MSB: 42 | type = ElfType::BE_64; 43 | break; 44 | default: 45 | throw std::runtime_error("Unimplemented"); 46 | } 47 | break; 48 | default: 49 | throw std::runtime_error("Unimplemented"); 50 | } 51 | 52 | // Cache EHDR 53 | s.seek(ehdr_offset, StreamSeek::Set); 54 | ehdr = parse(); 55 | } 56 | 57 | ElfParser::~ElfParser() { 58 | } 59 | 60 | Elf_Ehdr<> ElfParser::get_ehdr() { 61 | return ehdr; 62 | } 63 | 64 | Elf_Phdr<> ElfParser::get_phdr(size_t i) { 65 | assert(i < ehdr.e_phnum); 66 | s.seek(ehdr_offset + ehdr.e_phoff + ehdr.e_phentsize * i, StreamSeek::Set); 67 | return parse(); 68 | } 69 | 70 | Buffer ElfParser::get_pdata(size_t i) { 71 | const auto phdr = get_phdr(i); 72 | s.seek(ehdr_offset + phdr.p_offset, StreamSeek::Set); 73 | return s.read_b(phdr.p_filesz); 74 | } 75 | -------------------------------------------------------------------------------- /src/orbital/software/elf.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ELF Loader. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | // ELF conversion 16 | enum class ElfType { 17 | LE_32, 18 | BE_32, 19 | LE_64, 20 | BE_64, 21 | }; 22 | 23 | class ElfParser { 24 | Stream& s; 25 | ElfType type; 26 | 27 | size_t ehdr_offset; 28 | Elf_Ehdr<> ehdr; 29 | 30 | public: 31 | ElfParser(Stream& s); 32 | ~ElfParser(); 33 | 34 | /** 35 | * Get EHDR at the given index. 36 | */ 37 | Elf_Ehdr<> get_ehdr(); 38 | 39 | /** 40 | * Get PHDR at the given index. 41 | * @param[in] index PHDR index. 42 | */ 43 | Elf_Phdr<> get_phdr(size_t index); 44 | 45 | /** 46 | * Get segment/program data described by the PHDR at the given index. 47 | * @param[in] index PHDR index. 48 | */ 49 | Buffer get_pdata(size_t index); 50 | 51 | private: 52 | template typename S, typename T=Elf_TypeGeneric> 53 | S parse() { 54 | switch (type) { 55 | case ElfType::LE_32: 56 | return generalize(s.read_t>()); 57 | case ElfType::BE_32: 58 | return generalize(s.read_t>()); 59 | case ElfType::LE_64: 60 | return generalize(s.read_t>()); 61 | case ElfType::BE_64: 62 | return generalize(s.read_t>()); 63 | } 64 | } 65 | 66 | template 67 | static Elf_Ehdr<> generalize(const Elf_Ehdr& ehdr_t) { 68 | Elf_Ehdr<> ehdr = {}; 69 | memcpy(ehdr.e_ident, ehdr_t.e_ident, EI_NIDENT); 70 | ehdr.e_type = ehdr_t.e_type; 71 | ehdr.e_machine = ehdr_t.e_machine; 72 | ehdr.e_version = ehdr_t.e_version; 73 | ehdr.e_entry = ehdr_t.e_entry; 74 | ehdr.e_phoff = ehdr_t.e_phoff; 75 | ehdr.e_shoff = ehdr_t.e_shoff; 76 | ehdr.e_flags = ehdr_t.e_flags; 77 | ehdr.e_ehsize = ehdr_t.e_ehsize; 78 | ehdr.e_phentsize = ehdr_t.e_phentsize; 79 | ehdr.e_phnum = ehdr_t.e_phnum; 80 | ehdr.e_shentsize = ehdr_t.e_shentsize; 81 | ehdr.e_shnum = ehdr_t.e_shnum; 82 | ehdr.e_shstrndx = ehdr_t.e_shstrndx; 83 | return ehdr; 84 | } 85 | 86 | template 87 | static Elf_Phdr<> generalize(const Elf_Phdr& phdr_t) { 88 | Elf_Phdr<> phdr = {}; 89 | phdr.p_type = phdr_t.p_type; 90 | phdr.p_flags = phdr_t.p_flags; 91 | phdr.p_offset = phdr_t.p_offset; 92 | phdr.p_vaddr = phdr_t.p_vaddr; 93 | phdr.p_paddr = phdr_t.p_paddr; 94 | phdr.p_filesz = phdr_t.p_filesz; 95 | phdr.p_memsz = phdr_t.p_memsz; 96 | phdr.p_align = phdr_t.p_align; 97 | return phdr; 98 | } 99 | }; 100 | -------------------------------------------------------------------------------- /src/orbital/software/pup.h: -------------------------------------------------------------------------------- 1 | /** 2 | * PUP format. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | struct PupHeader { 19 | LE magic; 20 | LE version; 21 | LE mode; 22 | LE endian; 23 | LE attr; 24 | LE key_type; 25 | LE flags; 26 | LE hdr_size; 27 | LE meta_size; 28 | }; 29 | 30 | struct PupHeaderEx { 31 | LE file_size; 32 | LE segment_count; 33 | LE hash_count; 34 | LE flags; 35 | }; 36 | 37 | using PupSegmentEntry = CfSegment; 38 | using PupSegmentMeta = CfMeta; 39 | 40 | struct PupExtent { 41 | LE offset; 42 | LE size; 43 | }; 44 | 45 | struct PupDigest { 46 | std::byte data[32]; 47 | }; 48 | 49 | class PupParser : public CfParser { 50 | PupHeader header; 51 | PupHeaderEx headerEx; 52 | std::vector segEntries; 53 | std::vector segMetas; 54 | 55 | public: 56 | /** 57 | * Create PUP parser. 58 | * @param[in] verify Verify digital signatures. 59 | */ 60 | PupParser(Stream& s, bool verify=false); 61 | ~PupParser(); 62 | 63 | /** 64 | * Get PUP segment by identifier. 65 | * @param[in] id Segment identifier (44-bits). 66 | */ 67 | Buffer get(U64 id); 68 | 69 | private: 70 | /** 71 | * Get index of first PUP segment satisfying the given predicate, if any. 72 | * @param[in] pred Predicate function. 73 | */ 74 | U64 find(const std::function& pred) const; 75 | 76 | /** 77 | * Get index of first PUP segment with the given identifier, if any. 78 | * @param[in] id Segment identifier (44-bits). 79 | */ 80 | U64 find(U64 id) const; 81 | 82 | /** 83 | * Get index of the first information segment of a given PUP segment, if any. 84 | * @param[in] index Target segment index. 85 | */ 86 | U64 find_info(U64 id) const; 87 | 88 | /** 89 | * Get blocked PUP segment by identifier. 90 | * @param[in] id Segment identifier (44-bits). 91 | */ 92 | Buffer get_blocked(U64 index); 93 | 94 | /** 95 | * Get non-blocked PUP segment by identifier. 96 | * @param[in] id Segment identifier (44-bits). 97 | */ 98 | Buffer get_nonblocked(U64 index); 99 | }; 100 | -------------------------------------------------------------------------------- /src/orbital/software/self.h: -------------------------------------------------------------------------------- 1 | /** 2 | * SELF format. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | struct SelfHeader { 21 | LE magic; 22 | LE version; 23 | LE mode; 24 | LE endian; 25 | LE attr; 26 | LE key_type; 27 | LE header_size; 28 | LE meta_size; 29 | LE file_size; 30 | LE segment_count; 31 | LE flags; 32 | LE reserved; 33 | }; 34 | 35 | using SelfSegment = CfSegment; 36 | using SelfMeta = CfMeta; 37 | 38 | struct SelfInfo { 39 | LE paid; // Program Authority ID 40 | LE ptype; // Program Type 41 | LE version_app; // Application Version 42 | LE version_fw; // Firmware Version 43 | U08 digest[0x20]; 44 | }; 45 | 46 | class SelfParser : public CfParser { 47 | SelfHeader header; 48 | SelfInfo info; 49 | std::vector segments; 50 | std::vector metas; 51 | std::unique_ptr elf; 52 | 53 | public: 54 | SelfParser(Stream& s); 55 | ~SelfParser(); 56 | 57 | // ELF parser interface 58 | Elf_Ehdr<> get_ehdr(); 59 | 60 | Elf_Phdr<> get_phdr(size_t i); 61 | 62 | Buffer get_pdata(size_t i); 63 | 64 | private: 65 | /** 66 | * Get index of first segment whose identifier matches the given PHDR index, if any. 67 | * @param[in] id Segment identifier (44-bits). 68 | */ 69 | U64 find_segment(U64 phdr_idx) const; 70 | 71 | /** 72 | * Get blocked SELF segment by identifier. 73 | * @param[in] id Segment identifier (44-bits). 74 | */ 75 | Buffer get_segment_blocked(U64 index); 76 | 77 | /** 78 | * Get non-blocked SELF segment by identifier. 79 | * @param[in] id Segment identifier (44-bits). 80 | */ 81 | Buffer get_segment_nonblocked(U64 index); 82 | }; 83 | -------------------------------------------------------------------------------- /src/orbital/ui.h: -------------------------------------------------------------------------------- 1 | /** 2 | * SDL/ImGui-based user interface. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | #include 16 | 17 | #define SDL_MAIN_HANDLED 18 | #include 19 | 20 | #include "ui/imgui/imgui_impl_sdl.h" 21 | #include "ui/imgui/imgui_impl_vulkan.h" 22 | #include "ui/ui_orbital.h" 23 | 24 | // Forward declarations 25 | class VulkanManager; 26 | class PS4Machine; 27 | 28 | class UI { 29 | public: 30 | UI(); 31 | ~UI(); 32 | 33 | /** 34 | * Main UI loop. 35 | */ 36 | void task(PS4Machine& ps4); 37 | 38 | CharHost* get_uart0_backend() { return ui.get_uart0_backend(); } 39 | CharHost* get_uart1_backend() { return ui.get_uart1_backend(); } 40 | 41 | VulkanManager* get_vk() { 42 | return vk; 43 | } 44 | 45 | private: 46 | VulkanManager* vk; 47 | VkSurfaceKHR surface; 48 | VkDescriptorPool descriptor_pool; 49 | ImGui_ImplVulkanH_Window wd; 50 | 51 | SDL_Window* window; 52 | bool is_minimized; 53 | bool is_quitting; 54 | bool is_resized; 55 | int w; 56 | int h; 57 | 58 | // Orbital state 59 | OrbitalUI ui; 60 | 61 | /** 62 | * Main UI iteration. 63 | */ 64 | void loop(PS4Machine& ps4); 65 | 66 | void frame_render(); 67 | void frame_present(); 68 | 69 | /** 70 | * Initialize UI backend. 71 | */ 72 | static void initialize(); 73 | 74 | /** 75 | * Finalize UI backend. 76 | */ 77 | static void finalize(); 78 | }; 79 | -------------------------------------------------------------------------------- /src/orbital/ui/charhost_imgui.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * ImguiCharHost. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "charhost_imgui.h" 12 | #include "tool_logs.h" 13 | 14 | ImguiCharHost::ImguiCharHost(Object* parent, const ImguiCharHostConfig& config) 15 | : CharHost(parent), logs(config.logs) { 16 | } 17 | 18 | ImguiCharHost::~ImguiCharHost() { 19 | } 20 | 21 | U32 ImguiCharHost::get_features() const { 22 | return CH_FEAT_WRITE; 23 | } 24 | 25 | std::vector ImguiCharHost::read(size_t max_read) { 26 | assert_always("Unimplemented"); 27 | return {}; 28 | } 29 | 30 | size_t ImguiCharHost::write(const std::vector& data) { 31 | size_t count = 0; 32 | for (const auto& c : data) { 33 | logs->Log(c); 34 | } 35 | return count; 36 | } 37 | -------------------------------------------------------------------------------- /src/orbital/ui/charhost_imgui.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ImguiCharHost. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | // Forward declarations 16 | class ToolLogs; 17 | 18 | struct ImguiCharHostConfig { 19 | ToolLogs* logs = nullptr; 20 | }; 21 | 22 | class ImguiCharHost final : public CharHost { 23 | public: 24 | ImguiCharHost(Object* parent = nullptr, const ImguiCharHostConfig& config = {}); 25 | ~ImguiCharHost(); 26 | 27 | U32 get_features() const override; 28 | std::vector read(size_t max_read) override; 29 | size_t write(const std::vector& data) override; 30 | size_t read_data_avail() override { 31 | return 0; 32 | } 33 | 34 | private: 35 | ToolLogs* logs; 36 | }; 37 | -------------------------------------------------------------------------------- /src/orbital/ui/imgui/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2018 Omar Cornut 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/orbital/ui/imgui/imgui_impl_sdl.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Backend for SDL2 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | // (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.) 4 | 5 | // Implemented features: 6 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 7 | // [X] Platform: Clipboard support. 8 | // [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE). 9 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 10 | // Missing features: 11 | // [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. 12 | 13 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 14 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 15 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 16 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 17 | 18 | #pragma once 19 | #include "imgui.h" // IMGUI_IMPL_API 20 | 21 | struct SDL_Window; 22 | typedef union SDL_Event SDL_Event; 23 | 24 | IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); 25 | IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window); 26 | IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window); 27 | IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window); 28 | IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window); 29 | IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown(); 30 | IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(); 31 | IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event); 32 | 33 | #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS 34 | static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter 35 | #endif 36 | -------------------------------------------------------------------------------- /src/orbital/ui/imgui/widgets/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-2019 Omar Cornut 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/orbital/ui/tab.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * UI tab. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "tab.h" 12 | 13 | #define IMGUI_IMPL_API 14 | #include 15 | 16 | void Tab::begin_dockspace() { 17 | ImGui::SetNextWindowSize(ImVec2(400.0f, 400.0f)); 18 | ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.7f)); 19 | ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.0f, 0.0f, 0.0f, 0.7f)); 20 | ImGui::BeginChild("dockspace"); 21 | ImGui::PopStyleColor(2); 22 | ImGui::PushStyleColor(ImGuiCol_DockingEmptyBg, ImVec4(1.0f, 0.0f, 0.0f, 0.0f)); 23 | ImGuiID dockspace_id = ImGui::GetID("dockspace"); 24 | ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), 0); 25 | ImGui::PopStyleColor(); 26 | } 27 | 28 | void Tab::end_dockspace() { 29 | ImGui::EndChild(); 30 | } 31 | -------------------------------------------------------------------------------- /src/orbital/ui/tab.h: -------------------------------------------------------------------------------- 1 | /** 2 | * UI tab. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #define IMGUI_IMPL_API 14 | #include 15 | #include "imgui/widgets/imgui_memory_editor.h" 16 | 17 | class Tab { 18 | public: 19 | // Interface 20 | void begin_dockspace(); 21 | void end_dockspace(); 22 | }; 23 | -------------------------------------------------------------------------------- /src/orbital/ui/tab_cpu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * UI tab for CPU debugging. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | #include "tab.h" 15 | 16 | #include 17 | 18 | #define IMGUI_IMPL_API 19 | #include 20 | #include "imgui/widgets/imgui_memory_editor.h" 21 | 22 | // Forward declarations 23 | class PS4Machine; 24 | 25 | class TabCPU : public Tab { 26 | public: 27 | TabCPU(); 28 | 29 | // Interface 30 | void set_font_code(ImFont* font_code) { 31 | this->font_code = font_code; 32 | } 33 | void render(PS4Machine& ps4); 34 | 35 | private: 36 | ImFont* font_code; 37 | MemoryEditor me_stack; 38 | MemoryEditor me_memory; 39 | size_t cs_x86_16; 40 | size_t cs_x86_32; 41 | size_t cs_x86_64; 42 | 43 | // State 44 | size_t cpu_index = 0; 45 | uint64_t view_stack = 0; 46 | uint64_t view_memory = 0; 47 | 48 | // Helpers 49 | void render_disasm(X86CPUDevice* c); 50 | void render_state(X86CPUDevice* c); 51 | void render_stack(X86CPUDevice* c); 52 | void render_memory(X86CPUDevice* c); 53 | void render_breakpoints(X86CPUDevice* c); 54 | }; 55 | -------------------------------------------------------------------------------- /src/orbital/ui/tab_gpu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * UI tab for GPU debugging. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include "tab.h" 14 | 15 | #define IMGUI_IMPL_API 16 | #include 17 | #include "imgui/widgets/imgui_memory_editor.h" 18 | 19 | // Forward declarations 20 | class PS4Machine; 21 | class LiverpoolGCDevice; 22 | 23 | class TabGPU : public Tab { 24 | public: 25 | friend PS4Machine; 26 | TabGPU(); 27 | 28 | // Interface 29 | void set_font_code(ImFont* font_code) { 30 | this->font_code = font_code; 31 | } 32 | void render(PS4Machine& ps4); 33 | 34 | private: 35 | ImFont* font_code; 36 | 37 | // Helpers 38 | void render_dce(const LiverpoolGCDevice& c); 39 | void render_gfx(const LiverpoolGCDevice& c); 40 | void render_sam(const LiverpoolGCDevice& c); 41 | }; 42 | -------------------------------------------------------------------------------- /src/orbital/ui/tool_logs.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * UI tool for text logging. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #include "tool_logs.h" 12 | #include "charhost_imgui.h" 13 | 14 | ToolLogs::ToolLogs() { 15 | Backend = new ImguiCharHost(nullptr, { this }); 16 | } 17 | 18 | void ToolLogs::Clear() { 19 | Buf.clear(); 20 | LineOffsets.clear(); 21 | } 22 | 23 | void ToolLogs::Log(const char* fmt, ...) IM_FMTARGS(2) { 24 | int old_size = Buf.size(); 25 | va_list args; 26 | va_start(args, fmt); 27 | Buf.appendfv(fmt, args); 28 | va_end(args); 29 | for (int new_size = Buf.size(); old_size < new_size; old_size++) 30 | if (Buf[old_size] == '\n') 31 | LineOffsets.push_back(old_size); 32 | ScrollToBottom = true; 33 | } 34 | 35 | void ToolLogs::Log(char c) { 36 | ImVector& chars = Buf.Buf; 37 | if (c == '\n') 38 | LineOffsets.push_back(Buf.size()); 39 | chars.push_back(c); 40 | ScrollToBottom = true; 41 | } 42 | 43 | void ToolLogs::Draw(const char* title, bool* p_open) { 44 | ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiCond_FirstUseEver); 45 | if (!ImGui::Begin(title, p_open)) { 46 | ImGui::End(); 47 | return; 48 | } 49 | if (ImGui::Button("Clear")) Clear(); 50 | ImGui::SameLine(); 51 | bool copy = ImGui::Button("Copy"); 52 | ImGui::SameLine(); 53 | Filter.Draw("Filter", -100.0f); 54 | ImGui::Separator(); 55 | ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar); 56 | if (copy) ImGui::LogToClipboard(); 57 | 58 | if (Filter.IsActive()) { 59 | const char* buf_begin = Buf.begin(); 60 | const char* line = buf_begin; 61 | for (int line_no = 0; line != NULL; line_no++) { 62 | const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL; 63 | if (Filter.PassFilter(line, line_end)) 64 | ImGui::TextUnformatted(line, line_end); 65 | line = line_end && line_end[1] ? line_end + 1 : NULL; 66 | } 67 | } else { 68 | ImGui::TextUnformatted(Buf.begin()); 69 | } 70 | 71 | if (ScrollToBottom) 72 | ImGui::SetScrollHereY(1.0f); 73 | ScrollToBottom = false; 74 | ImGui::EndChild(); 75 | ImGui::End(); 76 | } 77 | -------------------------------------------------------------------------------- /src/orbital/ui/tool_logs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * UI tool for text logging. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | #define IMGUI_IMPL_API 16 | #include 17 | 18 | // Forward declarations 19 | class ImguiCharHost; 20 | 21 | class ToolLogs { 22 | public: 23 | ToolLogs(); 24 | 25 | CharHost* backend() { 26 | return reinterpret_cast(Backend); 27 | } 28 | 29 | void Clear(); 30 | void Log(const char* fmt, ...); 31 | void Log(char c); 32 | void Draw(const char* title, bool* p_open = nullptr); 33 | 34 | private: 35 | ImguiCharHost* Backend; 36 | ImGuiTextBuffer Buf; 37 | ImGuiTextFilter Filter; 38 | ImVector LineOffsets; 39 | bool ScrollToBottom; 40 | }; 41 | -------------------------------------------------------------------------------- /src/orbital/ui/ui_orbital.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Orbital UI renderer for ImGui. 3 | * 4 | * Copyright 2017-2021. Orbital project. 5 | * Released under MIT license. Read LICENSE for more details. 6 | * 7 | * Authors: 8 | * - Alexandro Sanchez Bach 9 | */ 10 | 11 | #pragma once 12 | 13 | #include "tab_cpu.h" 14 | #include "tab_gpu.h" 15 | #include "tool_logs.h" 16 | 17 | #define IMGUI_IMPL_API 18 | #include 19 | 20 | #include 21 | 22 | // Forward declarations 23 | class PS4Machine; 24 | 25 | class OrbitalUI { 26 | public: 27 | // Interface 28 | void init(); 29 | void render(PS4Machine& ps4); 30 | 31 | CharHost* get_uart0_backend(); 32 | CharHost* get_uart1_backend(); 33 | 34 | private: 35 | // Fonts 36 | ImFont* font_default{}; 37 | ImFont* font_text{}; 38 | ImFont* font_code{}; 39 | std::vector font_text_data; 40 | std::vector font_code_data; 41 | 42 | // Tabs 43 | TabCPU tab_cpu; 44 | TabGPU tab_gpu; 45 | 46 | // Tools 47 | ToolLogs tool_uart0{}; 48 | ToolLogs tool_uart1{}; 49 | MemoryEditor me_mem_gpa; 50 | 51 | // State 52 | bool show_stats; 53 | bool show_uart0 = true; 54 | bool show_uart1 = false; 55 | bool show_executing_processes; 56 | bool show_process_list; 57 | bool show_trace_cp; 58 | bool show_trace_icc; 59 | bool show_trace_samu; 60 | bool show_mem_gpa = false; 61 | bool show_mem_gva; 62 | bool show_mem_gart; 63 | bool show_mem_iommu; 64 | 65 | // Helpers 66 | void render_menus(PS4Machine& ps4); 67 | }; 68 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | CC ?= gcc 2 | AR ?= ar 3 | CC ?= gcc 4 | CXX ?= g++ 5 | 6 | CFLAGS = -Wall -Wextra -Og -g 7 | CXXFLAGS = -Wall -Wextra -Og -g -std=c++11 8 | ARC = $(wildcard *.a) 9 | OBJ = $(wildcard *.o) 10 | BIN = $(patsubst %.cpp, %.elf, $(wildcard *.cpp)) \ 11 | $(patsubst %.c, %.elf, $(wildcard *.c)) 12 | 13 | .PHONY: all clean 14 | 15 | all: $(BIN) 16 | 17 | clean: 18 | rm -f $(ARC) 19 | rm -f $(OBJ) 20 | rm -f $(BIN) 21 | 22 | # Tests 23 | test_gcn_disasm.elf: test_gcn_disasm.c 24 | $(CC) $(CFLAGS) -o $@ $< \ 25 | ../orbital-qemu/hw/ps4/liverpool/gca/gcn_parser.c \ 26 | ../orbital-qemu/hw/ps4/liverpool/gca/gcn_disasm.c \ 27 | -I../orbital-qemu/hw/ps4/liverpool/gca 28 | 29 | test_gcn_analyzer.elf: test_gcn_analyzer.c 30 | $(CC) $(CFLAGS) -o $@ $< \ 31 | ../orbital-qemu/hw/ps4/liverpool/gca/gcn_parser.c \ 32 | ../orbital-qemu/hw/ps4/liverpool/gca/gcn_analyzer.c \ 33 | ../orbital-qemu/hw/ps4/liverpool/gca/gcn_resource.c \ 34 | -I../orbital-qemu/hw/ps4/liverpool/gca 35 | 36 | test_gcn_translator.elf: test_gcn_translator.cpp libspirv.a 37 | $(CC) $(CFLAGS) -c \ 38 | ../orbital-qemu/hw/ps4/liverpool/gca/gcn_parser.c \ 39 | ../orbital-qemu/hw/ps4/liverpool/gca/gcn_analyzer.c \ 40 | ../orbital-qemu/hw/ps4/liverpool/gca/gcn_resource.c \ 41 | -I../orbital-qemu/hw/ps4/liverpool/gca 42 | $(CXX) $(CXXFLAGS) -o $@ $< gcn_parser.o gcn_analyzer.o gcn_resource.o \ 43 | ../orbital-qemu/hw/ps4/liverpool/gca/gcn_translator.cpp \ 44 | -I../orbital-qemu/hw/ps4/liverpool/gca \ 45 | -lSPIRV 46 | -------------------------------------------------------------------------------- /tests/test_gcn_analyzer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2019 Alexandro Sanchez Bach. All rights reserved. 3 | * Released under MIT license. Read LICENSE for more details. 4 | */ 5 | 6 | #include "gcn_analyzer.h" 7 | #include "gcn_parser.h" 8 | 9 | #include 10 | #include 11 | 12 | #define UNUSED(arg) (void)(arg) 13 | 14 | static int analyze_shader(const uint8_t *data, size_t size) 15 | { 16 | UNUSED(size); 17 | gcn_parser_t parser; 18 | gcn_analyzer_t analyzer; 19 | 20 | gcn_parser_init(&parser); 21 | gcn_analyzer_init(&analyzer); 22 | gcn_parser_parse(&parser, data, &gcn_analyzer_callbacks, &analyzer); 23 | gcn_analyzer_print(&analyzer, stdout); 24 | return 0; 25 | } 26 | 27 | int main(int argc, const char **argv) 28 | { 29 | size_t shader_size; 30 | uint8_t *shader_data; 31 | const char *name; 32 | FILE *file; 33 | int ret; 34 | 35 | if (argc <= 1) { 36 | fprintf(stderr, "Usage: %s [path/to/shader.bin]\n", argv[0]); 37 | return 0; 38 | } 39 | 40 | name = argv[1]; 41 | file = fopen(name, "rb"); 42 | if (!file) { 43 | fprintf(stderr, "File %s does not exist!\n", name); 44 | return 1; 45 | } 46 | fseek(file, 0, SEEK_END); 47 | shader_size = ftell(file); 48 | shader_data = malloc(shader_size); 49 | if (!shader_data) { 50 | fprintf(stderr, "Could not allocate 0x%zX bytes!\n", shader_size); 51 | return 1; 52 | } 53 | fseek(file, 0, SEEK_SET); 54 | if (fread(shader_data, 1, shader_size, file) != shader_size) { 55 | fprintf(stderr, "Could not read 0x%zX bytes!\n", shader_size); 56 | return 1; 57 | } 58 | ret = analyze_shader(shader_data, shader_size); 59 | free(shader_data); 60 | fclose(file); 61 | 62 | return ret; 63 | } 64 | -------------------------------------------------------------------------------- /tests/test_gcn_disasm.c: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2019 Alexandro Sanchez Bach. All rights reserved. 3 | * Released under MIT license. Read LICENSE for more details. 4 | */ 5 | 6 | #include "gcn_disasm.h" 7 | #include "gcn_parser.h" 8 | 9 | #include 10 | #include 11 | 12 | #define UNUSED(arg) (void)(arg) 13 | 14 | static int disasm_shader(const uint8_t *data, size_t size) 15 | { 16 | UNUSED(size); 17 | gcn_parser_t parser; 18 | gcn_disasm_t disasm; 19 | 20 | gcn_parser_init(&parser); 21 | gcn_disasm_init(&disasm); 22 | gcn_parser_parse(&parser, data, &gcn_disasm_callbacks, &disasm); 23 | return 0; 24 | } 25 | 26 | int main(int argc, const char **argv) 27 | { 28 | size_t shader_size; 29 | uint8_t *shader_data; 30 | const char *name; 31 | FILE *file; 32 | int ret; 33 | 34 | if (argc <= 1) { 35 | fprintf(stderr, "Usage: %s [path/to/shader.bin]\n", argv[0]); 36 | return 0; 37 | } 38 | 39 | name = argv[1]; 40 | file = fopen(name, "rb"); 41 | if (!file) { 42 | fprintf(stderr, "File %s does not exist!\n", name); 43 | return 1; 44 | } 45 | fseek(file, 0, SEEK_END); 46 | shader_size = ftell(file); 47 | shader_data = malloc(shader_size); 48 | if (!shader_data) { 49 | fprintf(stderr, "Could not allocate 0x%zX bytes!\n", shader_size); 50 | return 1; 51 | } 52 | fseek(file, 0, SEEK_SET); 53 | if (fread(shader_data, 1, shader_size, file) != shader_size) { 54 | fprintf(stderr, "Could not read 0x%zX bytes!\n", shader_size); 55 | return 1; 56 | } 57 | ret = disasm_shader(shader_data, shader_size); 58 | free(shader_data); 59 | fclose(file); 60 | 61 | return ret; 62 | } 63 | -------------------------------------------------------------------------------- /tests/test_gcn_translator.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2019 Alexandro Sanchez Bach. All rights reserved. 3 | * Released under MIT license. Read LICENSE for more details. 4 | */ 5 | 6 | #include "gcn_analyzer.h" 7 | #include "gcn_translator.h" 8 | #include "gcn_parser.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #define UNUSED(arg) (void)(arg) 15 | 16 | static int translate_shader(const uint8_t *data, size_t size, const char *stage) 17 | { 18 | UNUSED(size); 19 | gcn_parser_t parser; 20 | gcn_analyzer_t analyzer; 21 | gcn_translator_t *translator = NULL; 22 | uint8_t *bc_data; 23 | uint32_t bc_size; 24 | 25 | gcn_parser_init(&parser); 26 | gcn_analyzer_init(&analyzer); 27 | gcn_parser_parse(&parser, data, &gcn_analyzer_callbacks, &analyzer); 28 | 29 | if (!strcmp(stage, "ps")) 30 | translator = gcn_translator_create(&analyzer, GCN_STAGE_PS); 31 | if (!strcmp(stage, "vs")) 32 | translator = gcn_translator_create(&analyzer, GCN_STAGE_VS); 33 | if (!translator) 34 | return 1; 35 | 36 | gcn_parser_init(&parser); 37 | gcn_parser_parse(&parser, data, &gcn_translator_callbacks, translator); 38 | bc_data = gcn_translator_dump(translator, &bc_size); 39 | 40 | fwrite(bc_data, 1, bc_size, stdout); 41 | return 0; 42 | } 43 | 44 | int main(int argc, const char **argv) 45 | { 46 | size_t shader_size; 47 | uint8_t *shader_data; 48 | const char *name, *stage; 49 | FILE *file; 50 | int ret; 51 | 52 | if (argc <= 2) { 53 | fprintf(stderr, "Usage: %s {ps,vs} [path/to/shader.bin]\n", argv[0]); 54 | return 0; 55 | } 56 | 57 | stage = argv[1]; 58 | name = argv[2]; 59 | file = fopen(name, "rb"); 60 | if (!file) { 61 | fprintf(stderr, "File %s does not exist!\n", name); 62 | return 1; 63 | } 64 | fseek(file, 0, SEEK_END); 65 | shader_size = ftell(file); 66 | shader_data = reinterpret_cast(malloc(shader_size)); 67 | if (!shader_data) { 68 | fprintf(stderr, "Could not allocate 0x%zX bytes!\n", shader_size); 69 | return 1; 70 | } 71 | fseek(file, 0, SEEK_SET); 72 | if (fread(shader_data, 1, shader_size, file) != shader_size) { 73 | fprintf(stderr, "Could not read 0x%zX bytes!\n", shader_size); 74 | return 1; 75 | } 76 | ret = translate_shader(shader_data, shader_size, stage); 77 | free(shader_data); 78 | fclose(file); 79 | 80 | return ret; 81 | } 82 | -------------------------------------------------------------------------------- /tools/dumper/.gitignore: -------------------------------------------------------------------------------- 1 | # Temporaries 2 | build 3 | dump 4 | *.bin 5 | 6 | # Private 7 | private 8 | -------------------------------------------------------------------------------- /tools/dumper/Makefile: -------------------------------------------------------------------------------- 1 | LIBPS4 := $(PS4SDK)/libPS4 2 | 3 | TEXT := 0x926200000 4 | DATA := 0x926300000 5 | 6 | CC := gcc 7 | AS := gcc 8 | OBJCOPY := objcopy 9 | ODIR := build 10 | SDIR := source 11 | IDIRS := -I$(LIBPS4)/include -I. -Iinclude 12 | LDIRS := -L$(LIBPS4) -L. -Llib 13 | LIBS := -lPS4 14 | CFLAGS := $(IDIRS) -O2 -std=c11 -fno-builtin -nostartfiles -nostdlib -Wall -masm=intel -march=btver2 -mtune=btver2 -m64 -mabi=sysv -mcmodel=large -DTEXT_ADDRESS=$(TEXT) -DDATA_ADDRESS=$(DATA) 15 | SFLAGS := -nostartfiles -nostdlib -march=btver2 -mtune=btver2 16 | LFLAGS := $(LDIRS) -Xlinker -T $(LIBPS4)/linker.x -Wl,--build-id=none -Ttext=$(TEXT) -Tdata=$(DATA) 17 | CFILES := $(wildcard $(SDIR)/*.c) 18 | SFILES := $(wildcard $(SDIR)/*.s) 19 | OBJS := $(patsubst $(SDIR)/%.c, $(ODIR)/%.o, $(CFILES)) \ 20 | $(patsubst $(SDIR)/%.s, $(ODIR)/%.o, $(SFILES)) 21 | 22 | TARGET = $(shell basename $(CURDIR)).bin 23 | 24 | .PHONY: all 25 | all: 5.00 26 | 27 | .PHONY: 1.76 28 | 1.76: CFLAGS += -DVERSION_176 29 | 1.76: $(TARGET) 30 | 31 | .PHONY: 4.55 32 | 4.55: CFLAGS += -DVERSION_455 33 | 4.55: $(TARGET) 34 | 35 | .PHONY: 5.00 36 | 5.00: CFLAGS += -DVERSION_500 37 | 5.00: $(TARGET) 38 | 39 | .PHONY: 5.05 40 | 5.05: CFLAGS += -DVERSION_505 41 | 5.05: $(TARGET) 42 | 43 | $(TARGET): $(ODIR) $(OBJS) 44 | $(CC) $(LIBPS4)/crt0.s $(ODIR)/*.o -o temp.t $(CFLAGS) $(LFLAGS) $(LIBS) 45 | $(OBJCOPY) -O binary temp.t $(TARGET) 46 | rm -f temp.t 47 | 48 | $(ODIR)/%.o: $(SDIR)/%.c 49 | $(CC) -c -o $@ $< $(CFLAGS) 50 | 51 | $(ODIR)/%.o: $(SDIR)/%.s 52 | $(AS) -c -o $@ $< $(SFLAGS) 53 | 54 | $(ODIR): 55 | @mkdir $@ 56 | 57 | .PHONY: clean 58 | clean: 59 | rm -f $(TARGET) $(ODIR)/*.o 60 | -------------------------------------------------------------------------------- /tools/dumper/README.md: -------------------------------------------------------------------------------- 1 | Orbital Dumper 2 | ============== 3 | 4 | Dumper to dump/extract files required by Orbital from an actual PlayStation 4 console. 5 | The dumper currently supports PS4 FW ver 1.76, 4.55, 5.00, 5.05. 6 | 7 | ## Usage 8 | 9 | 1. Connect your computer and PS4 to the same network. 10 | 11 | 2. Setup [ps4-payload-sdk](https://github.com/xvortex/ps4-payload-sdk/). 12 | 13 | 3. Before building, change the IP address (`#define BLOBS_ADDR IP(192,168,2,1)`) found inside `source/blob.c` to the IP adress of the pc where the `server.py` will be running. 14 | 15 | 4. Build the payload for your firmware version with `make`. Pick one of the following supported firmware versions: 1.76, 4.55, 5.00, 5.05. For example: 16 | 17 | ```bash 18 | make 5.00 19 | ``` 20 | 21 | 5. Start the server with: 22 | 23 | ```bash 24 | python server.py 25 | ``` 26 | 27 | 6. Enter your computer's IP address in the PlayStation 4 web browser and follow the instructions on screen. The exploit provided by `server.py` only works for firmware 5.00. If you are on a different firmware you need to run an exploit manually and send the dumper payload using netcat/socat: 28 | 29 | ```bash 30 | socat -u FILE:dumper.bin TCP:"PS4 IP":9020 31 | ``` 32 | 33 | ## Development 34 | 35 | This dumper requires an exploit that listens for payloads in binary format on port `9020`. These payloads need to be mapped as follows in user address space: 36 | 37 | - `0x926200000`: Code (can be changed in `Makefile`) 38 | - `0x926300000`: Data (can be changed in `Makefile`) 39 | - `0x926400000`: Arguments (can be changed in `source/main.c`) 40 | 41 | Furthermore, the server will listen at port `9021` for incoming blobs, and optionally at `9022` for debug messages. 42 | 43 | ## Compiling Notes 44 | 45 | If you want to add support for a new FW, use one of the `source/ksdk_XXX.inc` as template and update the required offset to match that of your FW. 46 | -------------------------------------------------------------------------------- /tools/dumper/dumper.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, Helvetica, sans-serif; 3 | background-color: #313234; 4 | margin: 0 auto; 5 | padding: 0; 6 | width: 800px; 7 | height: 100%; 8 | font-size: 16px; 9 | color: #DDD; 10 | box-sizing: border-box; 11 | } 12 | 13 | /* Links */ 14 | a:link { color: #DDD; text-decoration: none; } 15 | a:visited { color: #DDD; text-decoration: none; } 16 | a:hover { color: #DDD; text-decoration: none; } 17 | a:active { color: #DDD; text-decoration: none; } 18 | 19 | /* Title */ 20 | #title { 21 | font-size: 32pt; 22 | font-weight: 100; 23 | text-align: center; 24 | text-transform: uppercase; 25 | letter-spacing: 0.05em; 26 | margin-top: 20px; 27 | } 28 | 29 | #subtitle { 30 | font-size: 16pt; 31 | font-weight: 100; 32 | text-align: center; 33 | text-transform: uppercase; 34 | letter-spacing: 0.1em; 35 | margin-bottom: 20px; 36 | } 37 | 38 | /* Information */ 39 | table th { 40 | font-size: 16pt; 41 | text-align: left; 42 | } 43 | tr { 44 | height: 1px; 45 | } 46 | th { 47 | width: 33.33%; 48 | } 49 | td { 50 | width: 33.33%; 51 | height: inherit; 52 | } 53 | td .button { 54 | height: calc(100% - 50px); 55 | margin-left: 5px; 56 | } 57 | 58 | .button { 59 | padding: 10px; 60 | background-color: #555; 61 | border-radius: 10px; 62 | user-select: none; 63 | } 64 | .button:hover { 65 | background-color: #666; 66 | cursor: pointer; 67 | } 68 | .button:active { 69 | background-color: #444; 70 | cursor: pointer; 71 | } 72 | .button.active { 73 | background-color: #444; 74 | } 75 | .button.disabled { 76 | cursor: not-allowed; 77 | color: #888; 78 | } 79 | .button.disabled:hover { 80 | background-color: #555; 81 | } 82 | 83 | #action { 84 | font-size: 18pt; 85 | font-weight: 100; 86 | margin-bottom: 20px; 87 | text-align: center; 88 | animation: floating-text 1s ease-in-out alternate infinite; 89 | } 90 | 91 | @keyframes floating-text { 92 | 0% { 93 | color: #AAA; 94 | text-shadow: 0px 0px 5px #AAA; 95 | } 96 | 100% { 97 | color: #EEE; 98 | text-shadow: 0px 0px 8px #EEE; 99 | } 100 | } 101 | 102 | #progress { 103 | width: 800px; 104 | margin-bottom: 20px; 105 | } 106 | 107 | #logs { 108 | width: 780px; 109 | padding: 10px; 110 | background-color: #212223; 111 | border-radius: 10px; 112 | font-family: "Lucida Console", Monaco, monospace; 113 | } 114 | 115 | #logs-internal { 116 | height: 200px; 117 | overflow-y: scroll; 118 | } 119 | -------------------------------------------------------------------------------- /tools/dumper/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Orbital Dumper 6 | 7 | 8 | 9 | 10 |
11 |
Orbital
12 |
Dumper
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 25 | 32 | 39 | 40 |
AboutOutput
22 |

Tool to dump/extract files required by Orbital from an actual PlayStation 4 console.

23 |

This takes few minutes and might fail/crash ocassionally depending on exploit reliability. If that happens, please restart the browser or the console.

24 |
26 |
27 | USB 28 |

Dump system files to a connected USB flash drive.

29 |

30 |
31 |
33 |
34 | Network 35 |

Dump system files to a WebSockets server.

36 |

37 |
38 |
41 | 42 |
43 | Start 44 |
45 |
46 |
47 |
48 |
49 |
50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /tools/dumper/source/blob.c: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2018 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | */ 5 | 6 | #include "blob.h" 7 | 8 | #include "ksdk.h" 9 | #include "md5.h" 10 | #include "debug.h" 11 | 12 | #define BLOBS_ADDR IP(192,168,2,1); 13 | #define BLOBS_PORT 9021 14 | 15 | int blobs_sockfd = 0; 16 | 17 | /* blobs */ 18 | blob_t* blob_add(blob_t *blob) 19 | { 20 | blob_t *next = malloc(sizeof(blob_t)); 21 | memset(next, 0, sizeof(blob_t)); 22 | blob->next = next; 23 | return next; 24 | } 25 | 26 | void blob_set_path(blob_t *blob, const char *path) 27 | { 28 | blob->path = strdup(path); 29 | } 30 | 31 | void blob_set_path_hash(blob_t *blob, const uint8_t *data, size_t size) 32 | { 33 | uint8_t hash[16]; 34 | char path[256]; 35 | char *p; 36 | 37 | MD5_CTX ctx; 38 | MD5_Init(&ctx); 39 | MD5_Update(&ctx, data, size); 40 | MD5_Final(hash, &ctx); 41 | 42 | strncpy(path, "crypto/", sizeof(path)); 43 | p = strrchr(path, '/') + 1; 44 | for (size_t i = 0; i < sizeof(hash); i++) { 45 | snprintf(p, 3, "%02X", hash[i]); 46 | p += 2; 47 | } 48 | strncpy(p, ".bin", sizeof(path) - (p - &path[0])); 49 | blob_set_path(blob, path); 50 | } 51 | 52 | void blob_transfer_init() 53 | { 54 | struct sockaddr_in server; 55 | memset(&server, 0, sizeof(server)); 56 | server.sin_len = sizeof(server); 57 | server.sin_family = AF_INET; 58 | server.sin_addr.s_addr = BLOBS_ADDR; 59 | server.sin_port = sceNetHtons(BLOBS_PORT); 60 | 61 | blobs_sockfd = sceNetSocket("blobs", AF_INET, SOCK_STREAM, 0); 62 | sceNetConnect(blobs_sockfd, (struct sockaddr *)&server, sizeof(server)); 63 | } 64 | 65 | void blob_transfer_close() 66 | { 67 | sceNetSocketClose(blobs_sockfd); 68 | } 69 | 70 | static void blob_transfer_via_net(blob_t *blob) 71 | { 72 | size_t path_size; 73 | 74 | path_size = strlen(blob->path); 75 | sceNetSend(blobs_sockfd, &path_size, sizeof(path_size), 0); 76 | sceNetSend(blobs_sockfd, &blob->path[0], path_size, 0); 77 | sceNetSend(blobs_sockfd, &blob->size, sizeof(blob->size), 0); 78 | sceNetSend(blobs_sockfd, &blob->data[0], blob->size, 0); 79 | } 80 | 81 | static void blob_transfer_via_usb(blob_t *blob) 82 | { 83 | dprintf("Unimplemented\n"); 84 | } 85 | 86 | void blob_transfer(blob_t *blob, int mode) 87 | { 88 | if (!blob) { 89 | return; 90 | } 91 | switch (mode) { 92 | case BLOB_TRANSFER_NET: 93 | blob_transfer_via_net(blob); 94 | break; 95 | case BLOB_TRANSFER_USB: 96 | blob_transfer_via_usb(blob); 97 | break; 98 | default: 99 | dprintf("Unimplemented\n"); 100 | } 101 | } 102 | 103 | void blob_transfer_all(blob_t *blobs, int mode) 104 | { 105 | while (blobs) { 106 | if (blobs->data) { 107 | blob_transfer(blobs, mode); 108 | } 109 | blobs = blobs->next; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /tools/dumper/source/blob.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2018 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | */ 5 | 6 | #ifndef BLOB_H 7 | #define BLOB_H 8 | 9 | #include "ksdk.h" 10 | 11 | #define BLOB_TRANSFER_NET 1 12 | #define BLOB_TRANSFER_USB 2 13 | 14 | typedef struct blob_t { 15 | struct blob_t *next; 16 | char *path; 17 | size_t size; 18 | uint8_t *data; 19 | } blob_t; 20 | 21 | blob_t* blob_add(blob_t *blob); 22 | void blob_set_path_hash(blob_t *blob, const uint8_t *data, size_t size); 23 | void blob_set_path(blob_t *blob, const char *name); 24 | 25 | void blob_transfer_init(); 26 | void blob_transfer_close(); 27 | void blob_transfer(blob_t *blob, int mode); 28 | void blob_transfer_all(blob_t *blobs, int mode); 29 | 30 | #endif /* BLOB_H */ 31 | -------------------------------------------------------------------------------- /tools/dumper/source/debug.c: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2018 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | */ 5 | 6 | #include "debug.h" 7 | 8 | /* debugging */ 9 | #define DEBUG 1 10 | #define DEBUG_ADDR IP(192,168,2,1); 11 | #define DEBUG_PORT 9022 12 | 13 | #define ku_dprintf(...) do { \ 14 | if (kernel) kdprintf(__VA_ARGS__); else dprintf(__VA_ARGS__); \ 15 | } while(0) 16 | 17 | int debug_sockfd; 18 | char debug_tmp[512]; 19 | 20 | void debug_init() 21 | { 22 | if (!DEBUG) return; 23 | 24 | struct sockaddr_in server; 25 | memset(&server, 0, sizeof(server)); 26 | server.sin_len = sizeof(server); 27 | server.sin_family = AF_INET; 28 | server.sin_addr.s_addr = DEBUG_ADDR; 29 | server.sin_port = sceNetHtons(DEBUG_PORT); 30 | 31 | debug_sockfd = sceNetSocket("debug", AF_INET, SOCK_STREAM, 0); 32 | sceNetConnect(debug_sockfd, (struct sockaddr *)&server, sizeof(server)); 33 | } 34 | 35 | void debug_close() 36 | { 37 | if (!DEBUG) return; 38 | sceNetSocketClose(debug_sockfd); 39 | } 40 | 41 | void _dputs(const char *msg) 42 | { 43 | sceNetSend(debug_sockfd, msg, strlen(msg), 0); 44 | } 45 | 46 | void _kdputs(const char *msg) 47 | { 48 | uint64_t len = strlen(msg); 49 | memcpy(debug_tmp, msg, len); 50 | write_args uap; 51 | uap.fd = debug_sockfd; 52 | uap.buf = debug_tmp; 53 | uap.nbyte = len; 54 | sys_write(curthread(), &uap); 55 | } 56 | 57 | void _hexdump(char *desc, void *addr, int len, int kernel) { 58 | int i; 59 | unsigned char buff[17]; 60 | unsigned char *pc = (unsigned char*)addr; 61 | 62 | if (desc != NULL) 63 | ku_dprintf ("%s:\n", desc); 64 | 65 | if (len == 0) { 66 | ku_dprintf(" ZERO LENGTH\n"); 67 | return; 68 | } 69 | if (len < 0) { 70 | ku_dprintf(" NEGATIVE LENGTH: %i\n",len); 71 | return; 72 | } 73 | for (i = 0; i < len; i++) { 74 | if ((i % 16) == 0) { 75 | if (i != 0) 76 | ku_dprintf (" %s\n", buff); 77 | ku_dprintf (" %04x ", i); 78 | } 79 | ku_dprintf (" %02x", pc[i]); 80 | if ((pc[i] < 0x20) || (pc[i] > 0x7e)) 81 | buff[i % 16] = '.'; 82 | else 83 | buff[i % 16] = pc[i]; 84 | buff[(i % 16) + 1] = '\0'; 85 | } 86 | while ((i % 16) != 0) { 87 | ku_dprintf (" "); 88 | i++; 89 | } 90 | ku_dprintf (" %s\n", buff); 91 | } 92 | -------------------------------------------------------------------------------- /tools/dumper/source/debug.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2018 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | */ 5 | 6 | #ifndef DEBUG_H 7 | #define DEBUG_H 8 | 9 | #include "ksdk.h" 10 | 11 | #define dprintf(format, ...)\ 12 | do {\ 13 | char debug_msg[512];\ 14 | snprintf(debug_msg, 512, format, ##__VA_ARGS__);\ 15 | dputs(debug_msg);\ 16 | } while(0) 17 | 18 | #define kdprintf(format, ...)\ 19 | do {\ 20 | char debug_msg[512];\ 21 | snprintf(debug_msg, 512, format, ##__VA_ARGS__);\ 22 | kdputs(debug_msg);\ 23 | } while(0) 24 | 25 | #define dputs(msg) \ 26 | _dputs(msg); 27 | #define kdputs(msg) \ 28 | _kdputs(msg); 29 | #define hexdump(desc, addr, len) \ 30 | _hexdump((desc), (addr), (len), 0); 31 | #define khexdump(desc, addr, len) \ 32 | _hexdump((desc), (addr), (len), 1); 33 | 34 | extern int debug_sockfd; 35 | 36 | void debug_init(); 37 | void debug_close(); 38 | 39 | void _dputs(const char *msg); 40 | void _kdputs(const char *msg); 41 | void _hexdump(char *desc, void *addr, int len, int kernel); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /tools/dumper/source/gpu_dumper.c: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2019 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | * 5 | * Based in previous tools and research by: fail0verflow, flatz. 6 | */ 7 | 8 | #ifdef VERSION_500 9 | 10 | #include "gpu_dumper.h" 11 | #include "debug.h" 12 | 13 | #include "ksdk.h" 14 | 15 | typedef struct gpu_dump_ih_info_t { 16 | /* gpu information */ 17 | uint32_t rb_rptr; 18 | uint32_t rb_wptr; 19 | /* cpu information */ 20 | void *rb_base; 21 | /* ih ringbuffer */ 22 | uint8_t rb[0x1000]; 23 | } gpu_dump_ih_info_t; 24 | 25 | /* kernel */ 26 | typedef struct gpu_kdump_ih_args_t { 27 | gpu_dump_ih_info_t *uinfo; 28 | } gpu_kdump_ih_args_t; 29 | 30 | typedef struct gpu_kmethod_uap_t { 31 | void *kmethod; 32 | void *args; 33 | } gpu_kmethod_uap_t; 34 | 35 | int gpu_kdump_ih( 36 | struct thread *td, struct gpu_kmethod_uap_t *uap) 37 | { 38 | int ret; 39 | gpu_kdump_ih_args_t *args = uap->args; 40 | gpu_dump_ih_info_t info; 41 | 42 | ret = 0; 43 | info.rb_wptr = 0x4567; 44 | info.rb_base = g_ih_mgr->rb_base; 45 | memcpy(&info.rb, g_ih_mgr->rb_base, 0x1000); 46 | memcpy(args->uinfo, &info, sizeof(info)); 47 | 48 | return ret; 49 | } 50 | 51 | int gpu_dump_ih() 52 | { 53 | gpu_dump_ih_info_t info; 54 | gpu_kdump_ih_args_t args; 55 | 56 | args.uinfo = &info; 57 | info.rb_rptr = 0x1234; 58 | syscall(11, gpu_kdump_ih, &args); 59 | dprintf("rb_rptr %X\n", info.rb_rptr); 60 | dprintf("rb_wptr %X\n", info.rb_wptr); 61 | dprintf("rb_base %p\n", info.rb_base); 62 | hexdump("rb", &info.rb, 0x1000); 63 | return 0; 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /tools/dumper/source/gpu_dumper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2019 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | * 5 | * Based in previous tools and research by: fail0verflow, flatz. 6 | */ 7 | 8 | #ifndef GPU_DUMPER_H 9 | #define GPU_DUMPER_H 10 | 11 | /* functions */ 12 | int gpu_dump_ih(); 13 | 14 | #endif /* GPU_DUMPER_H */ 15 | -------------------------------------------------------------------------------- /tools/dumper/source/ksdk.c: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2018 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | */ 5 | 6 | #include "ksdk.h" 7 | 8 | #define KFUNC(slide, name, ret, args) \ 9 | ret (*name) args 10 | #define KDATA(slide, name, type) \ 11 | type* name 12 | #include "ksdk.inc" 13 | #undef KFUNC 14 | #undef KDATA 15 | 16 | static inline __attribute__((always_inline)) 17 | uint64_t get_kbase() { 18 | uint64_t base; 19 | uint32_t edx, eax; 20 | __asm__ ("rdmsr" : "=d"(edx), "=a"(eax) : "c"(0xC0000082)); 21 | base = ((((uint64_t)edx) << 32) | (uint64_t)eax) - 448; 22 | return base; 23 | } 24 | 25 | #define KSLIDE(offset) \ 26 | (void*)(kbase + offset); 27 | 28 | void init_ksdk() { 29 | uint8_t* kbase = (uint8_t*)get_kbase(); 30 | #define KFUNC(slide, name, ret, args) \ 31 | name = KSLIDE(slide) 32 | #define KDATA(slide, name, type) \ 33 | name = KSLIDE(slide) 34 | #include "ksdk.inc" 35 | #undef KFUNC 36 | #undef KDATA 37 | } 38 | -------------------------------------------------------------------------------- /tools/dumper/source/ksdk.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2018 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | */ 5 | 6 | #ifndef KSDK_H 7 | #define KSDK_H 8 | 9 | #include "ps4.h" 10 | 11 | #include "ksdk_bsd.h" 12 | #include "ksdk_gpu.h" 13 | #include "ksdk_sbl.h" 14 | #include "ksdk_util.h" 15 | 16 | #ifdef __GNUC__ 17 | #define __cdecl __attribute__((cdecl)) 18 | #define __fastcall __attribute__((fastcall)) 19 | #endif 20 | 21 | #define false 0 22 | #define true 1 23 | 24 | #define KFUNC(slide, name, ret, args) \ 25 | extern ret (*name) args 26 | #define KDATA(slide, name, type) \ 27 | extern type* name 28 | #include "ksdk.inc" 29 | #undef KFUNC 30 | #undef KDATA 31 | 32 | void init_ksdk(); 33 | 34 | #endif /* KSDK_H */ 35 | -------------------------------------------------------------------------------- /tools/dumper/source/ksdk.inc: -------------------------------------------------------------------------------- 1 | #ifdef VERSION_176 2 | #include "ksdk_176.inc" 3 | #elif VERSION_455 4 | # include "ksdk_455.inc" 5 | #elif VERSION_500 6 | #include "ksdk_500.inc" 7 | #elif VERSION_505 8 | #include "ksdk_505.inc" 9 | #else 10 | #error "Target firmware not yet supported." 11 | #endif 12 | -------------------------------------------------------------------------------- /tools/dumper/source/ksdk_455.inc: -------------------------------------------------------------------------------- 1 | /* functions */ 2 | KFUNC(0x0038FA30, _sx_xlock, int, (void *sx, int opts, const char *file, int line)); 3 | KFUNC(0x0038FBC0, _sx_xunlock, void, (void *sx, const char *file, int line)); 4 | KFUNC(0x003F7750, kmalloc, void *, (uint64_t size, void *area, uint64_t flags)); 5 | KFUNC(0x003F7930, kfree, void, (void *ptr, void *area)); 6 | KFUNC(0x0005F1A0, sys_write, void, (void *td, void *uap)); 7 | KFUNC(0x005FFD90, sceSblDriverMapPages, int, (uint64_t *gpu_paddr, void *cpu_vaddr, uint32_t npages, uint64_t flags, uint64_t unk, uint64_t *gpu_desc)); 8 | KFUNC(0x00600450, sceSblDriverUnmapPages, int, (uint64_t gpu_desc)); 9 | KFUNC(0x00612940, map_chunk_table, int, (uint64_t *gpu_paddr, uint64_t *gpu_desc, void *cpu_vaddr)); 10 | KFUNC(0x006146C0, sceSblServiceMailbox, int, (uint64_t module_id, void *query, void *reply)); 11 | KFUNC(0x0061FB50, _sceSblAuthMgrSmFinalize, int, (void *ctx)); 12 | 13 | /* globals */ 14 | KDATA(0x010399B0, prison0, void*); 15 | KDATA(0x01A3A330, M_AUTHMGR, void); 16 | KDATA(0x021AFA30, rootvnode, void*); 17 | KDATA(0x025642F0, sceSblAuthMgrModuleId, uint64_t); 18 | KDATA(0x025640A8, authmgr_sm_xlock, void); 19 | KDATA(0x02564110, self_ctx_status, uint32_t); 20 | KDATA(0x02564120, self_contexts, self_context_t); 21 | 22 | // TODO: Apply the patches below 23 | #if 0 24 | ////// main.c ////// 25 | void kpatch_enablemapself(struct thread *td) 26 | { 27 | uint8_t *kmem; 28 | cpu_disable_wp(); 29 | 30 | /* update offsets (4.55) */ 31 | uint8_t* kernel_base = &((uint8_t*)read_msr(0xC0000082))[-0x3095D0]; 32 | uint8_t* map_self_patch1 = &kernel_base[0x143BF2]; 33 | uint8_t* map_self_patch2 = &kernel_base[0x143E0E]; 34 | 35 | 36 | kmem = (uint8_t*)map_self_patch1; 37 | kmem[0] = 0x90; 38 | kmem[1] = 0xE9; 39 | 40 | kmem = (uint8_t*)map_self_patch2; 41 | kmem[0] = 0x90; 42 | kmem[1] = 0x90; 43 | 44 | cpu_enable_wp(); 45 | } 46 | #endif 47 | -------------------------------------------------------------------------------- /tools/dumper/source/ksdk_500.inc: -------------------------------------------------------------------------------- 1 | /* functions */ 2 | KFUNC(0x000F5D00, _sx_xlock, int, (void *sx, int opts, const char *file, int line)); 3 | KFUNC(0x000F5EC0, _sx_xunlock, void, (void *sx, const char *file, int line)); 4 | KFUNC(0x0010E140, kmalloc, void *, (uint64_t size, void *area, uint64_t flags)); 5 | KFUNC(0x0010E350, kfree, void, (void *ptr, void *area)); 6 | KFUNC(0x00152EB0, sys_write, void, (void *td, void *uap)); 7 | KFUNC(0x0061B9B0, sceSblDriverMapPages, int, (uint64_t *gpu_paddr, void *cpu_vaddr, uint32_t npages, uint64_t flags, uint64_t unk, uint64_t *gpu_desc)); 8 | KFUNC(0x0061C080, sceSblDriverUnmapPages, int, (uint64_t gpu_desc)); 9 | KFUNC(0x0062FFD0, map_chunk_table, int, (uint64_t *gpu_paddr, uint64_t *gpu_desc, void *cpu_vaddr)); 10 | KFUNC(0x00630020, make_chunk_table, int, (uint64_t *segment_info_gpu_paddr, uint64_t *segment_info_gpu_desc, void *segment_info_cpu_vaddr, size_t segment_info_size, void *chunk_table_cpu_vaddr, size_t chunk_table_size, int type)); 11 | KFUNC(0x00632160, sceSblServiceMailbox, int, (uint64_t module_id, void *query, void *reply)); 12 | KFUNC(0x00632010, sceSblServiceSpawn, int, (char *module_name, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint64_t *module_id)); 13 | KFUNC(0x00642460, _sceSblAuthMgrSmFinalize, int, (void *ctx)); 14 | 15 | /* globals */ 16 | KDATA(0x010986A0, prison0, void*); 17 | KDATA(0x01A727E0, M_AUTHMGR, void); 18 | KDATA(0x022C19F0, rootvnode, void*); 19 | KDATA(0x024CF328, g_ih_mgr, gpu_ih_mgr_t); 20 | KDATA(0x02768310, sceSblAuthMgrModuleId, uint64_t); 21 | KDATA(0x027680D0, authmgr_sm_xlock, void); 22 | KDATA(0x02768140, self_ctx_status, uint32_t); 23 | KDATA(0x02768150, self_contexts, self_context_t); 24 | -------------------------------------------------------------------------------- /tools/dumper/source/ksdk_505.inc: -------------------------------------------------------------------------------- 1 | /* functions */ 2 | KFUNC(0x000F5E10, _sx_xlock, int, (void *sx, int opts, const char *file, int line)); 3 | KFUNC(0x000F5FD0, _sx_xunlock, void, (void *sx, const char *file, int line)); 4 | KFUNC(0x0010E250, kmalloc, void *, (uint64_t size, void *area, uint64_t flags)); 5 | KFUNC(0x0010E460, kfree, void, (void *ptr, void *area)); 6 | KFUNC(0x00152FC0, sys_write, void, (void *td, void *uap)); 7 | KFUNC(0x0061BD90, sceSblDriverMapPages, int, (uint64_t *gpu_paddr, void *cpu_vaddr, uint32_t npages, uint64_t flags, uint64_t unk, uint64_t *gpu_desc)); 8 | KFUNC(0x0061C460, sceSblDriverUnmapPages, int, (uint64_t gpu_desc)); 9 | KFUNC(0x006303B0, map_chunk_table, int, (uint64_t *gpu_paddr, uint64_t *gpu_desc, void *cpu_vaddr)); 10 | KFUNC(0x00630400, make_chunk_table, int, (uint64_t *segment_info_gpu_paddr, uint64_t *segment_info_gpu_desc, void *segment_info_cpu_vaddr, size_t segment_info_size, void *chunk_table_cpu_vaddr, size_t chunk_table_size, int type)); 11 | KFUNC(0x00632540, sceSblServiceMailbox, int, (uint64_t module_id, void *query, void *reply)); 12 | KFUNC(0x006323F0, sceSblServiceSpawn, int, (char *module_name, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint64_t *module_id)); 13 | KFUNC(0x00642840, _sceSblAuthMgrSmFinalize, int, (void *ctx)); 14 | 15 | /* globals */ 16 | KDATA(0x010986A0, prison0, void*); 17 | KDATA(0x01A727E0, M_AUTHMGR, void); 18 | KDATA(0x022C1A70, rootvnode, void*); 19 | KDATA(0x02768310, sceSblAuthMgrModuleId, uint64_t); 20 | KDATA(0x027680D0, authmgr_sm_xlock, void); 21 | KDATA(0x02768140, self_ctx_status, uint32_t); 22 | KDATA(0x02768150, self_contexts, self_context_t); 23 | -------------------------------------------------------------------------------- /tools/dumper/source/ksdk_bsd.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2018 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | */ 5 | 6 | #ifndef KSDK_BSD_H 7 | #define KSDK_BSD_H 8 | 9 | /* constants */ 10 | #define DT_DIR 0x0004 11 | #define DT_REG 0x0008 12 | 13 | #define M_NOWAIT 0x0001 14 | #define M_WAITOK 0x0002 15 | #define M_ZERO 0x0100 16 | 17 | struct auditinfo_addr { 18 | char useless[184]; 19 | }; 20 | 21 | struct ucred { 22 | uint32_t cr_ref; 23 | uint32_t cr_uid; 24 | uint32_t cr_ruid; 25 | uint32_t cr_svuid; 26 | uint32_t cr_ngroups; 27 | uint32_t cr_rgid; 28 | uint32_t cr_svgid; 29 | void *cr_uidinfo; 30 | void *cr_ruidinfo; 31 | void *cr_prison; 32 | void *cr_loginclass; 33 | uint32_t cr_flags; 34 | void *cr_pspare2[2]; 35 | void *cr_label; 36 | struct auditinfo_addr cr_audit; 37 | uint32_t *cr_groups; 38 | uint32_t cr_agroups; 39 | }; 40 | 41 | struct filedesc { 42 | void *useless1[3]; 43 | void *fd_rdir; 44 | void *fd_jdir; 45 | }; 46 | 47 | struct proc { 48 | char useless[64]; 49 | struct ucred *p_ucred; 50 | struct filedesc *p_fd; 51 | }; 52 | 53 | struct thread { 54 | void *useless; 55 | struct proc *td_proc; 56 | }; 57 | 58 | typedef struct write_args { 59 | int64_t fd; 60 | const void *buf; 61 | size_t nbyte; 62 | } write_args; 63 | 64 | #endif /* KSDK_BSD_H */ 65 | -------------------------------------------------------------------------------- /tools/dumper/source/ksdk_gpu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2018 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | */ 5 | 6 | #ifndef KSDK_GPU_H 7 | #define KSDK_GPU_H 8 | 9 | /* self */ 10 | typedef struct gpu_ih_mgr_t { 11 | uint8_t unk[0x58]; 12 | void *rb_base; 13 | } gpu_ih_mgr_t; 14 | 15 | #endif /* KSDK_GPU_H */ 16 | -------------------------------------------------------------------------------- /tools/dumper/source/ksdk_sbl.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2018 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | */ 5 | 6 | #ifndef KSDK_SBL_H 7 | #define KSDK_SBL_H 8 | 9 | /* pupmgr */ 10 | #define PUPMGR_CMD_DECRYPT_HEADER 0x01 11 | #define PUPMGR_CMD_DECRYPT_SEGMENT 0x04 12 | #define PUPMGR_CMD_VERIFY_HEADER 0x0F 13 | 14 | typedef struct sbl_pupmgr_decrypt_segment_t { 15 | uint32_t function; 16 | uint32_t status; 17 | uint64_t chunk_table_addr; 18 | uint16_t segment_index; 19 | uint16_t unk_0A; // zero 20 | uint32_t unk_0C; // zero 21 | } sbl_pupmgr_decrypt_segment_t; 22 | 23 | typedef struct sbl_pupmgr_exit_t { 24 | uint32_t function; 25 | uint32_t status; 26 | } sbl_pupmgr_exit_t; 27 | 28 | /* authmgr */ 29 | #define AUTHMGR_CMD_VERIFY_HEADER 0x01 30 | #define AUTHMGR_CMD_LOAD_SELF_SEGMENT 0x02 31 | #define AUTHMGR_CMD_LOAD_SELF_BLOCK 0x06 32 | 33 | typedef struct sbl_authmgr_chunk_entry_t { 34 | uint64_t data_addr; 35 | uint64_t data_size; 36 | } sbl_authmgr_chunk_entry_t; 37 | 38 | typedef struct sbl_authmgr_chunk_table_t { 39 | uint64_t data_addr; 40 | uint64_t data_size; 41 | uint64_t num_entries; 42 | uint64_t reserved; 43 | sbl_authmgr_chunk_entry_t entries[0]; 44 | } sbl_authmgr_chunk_table_t; 45 | 46 | typedef struct sbl_authmgr_verify_header_t { 47 | uint32_t function; 48 | uint32_t status; 49 | uint64_t header_addr; 50 | uint32_t header_size; 51 | uint32_t zero_0C; 52 | uint32_t zero_10; 53 | uint32_t context_id; 54 | uint64_t auth_info_addr; 55 | uint32_t unk_20; 56 | uint32_t key_id; 57 | uint8_t key[0x10]; 58 | } sbl_authmgr_verify_header_t; 59 | 60 | typedef struct sbl_authmgr_load_self_segment_t { 61 | uint32_t function; 62 | uint32_t status; 63 | uint64_t chunk_table_addr; 64 | uint32_t segment_index; 65 | uint32_t is_block_table; 66 | uint64_t zero_10; 67 | uint64_t zero_18; 68 | uint32_t zero_20; 69 | uint32_t zero_24; 70 | uint32_t context_id; 71 | } sbl_authmgr_load_self_segment_t; 72 | 73 | typedef struct sbl_authmgr_load_self_block_t { 74 | uint32_t function; 75 | uint32_t status; 76 | uint64_t pages_addr; 77 | uint32_t segment_index; 78 | uint32_t context_id; 79 | uint8_t digest[0x20]; 80 | uint8_t extent[0x8]; 81 | uint32_t block_index; 82 | uint32_t data_offset; 83 | uint32_t data_size; 84 | uint64_t data_start_addr; 85 | uint64_t data_end_addr; 86 | uint32_t zero; 87 | } sbl_authmgr_load_self_block_t; 88 | 89 | /* self */ 90 | typedef struct self_context_t { 91 | uint32_t format; 92 | uint32_t elf_auth_type; 93 | uint32_t total_header_size; 94 | uint32_t unk_0C; 95 | void *segment; 96 | uint32_t unk_18; 97 | uint32_t ctx_id; 98 | uint64_t svc_id; 99 | uint64_t unk_28; 100 | uint32_t buf_id; 101 | uint32_t unk_34; 102 | struct self_header_t *header; 103 | uint8_t mtx_struct[0x20]; 104 | } self_context_t; 105 | 106 | #define sceSblServiceMailbox_locked(ret, id, iptr, optr) do { \ 107 | _sx_xlock(authmgr_sm_xlock, 0, NULL, 0); \ 108 | ret = sceSblServiceMailbox((id), (iptr), (optr)); \ 109 | _sx_xunlock(authmgr_sm_xlock, NULL, 0); \ 110 | } while (0) 111 | 112 | #endif /* KSDK_SBL_H */ 113 | -------------------------------------------------------------------------------- /tools/dumper/source/ksdk_util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2018 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | */ 5 | 6 | #ifndef UTIL_H 7 | #define UTIL_H 8 | 9 | #define MIN(X, Y) \ 10 | (((X) < (Y)) ? (X) : (Y)) 11 | #define MAX(X, Y) \ 12 | (((X) > (Y)) ? (X) : (Y)) 13 | 14 | #define ROTL16(v, n) \ 15 | ((uint16_t)((v) << (n)) | ((v) >> (16 - (n)))) 16 | #define ROTL32(v, n) \ 17 | ((uint32_t)((v) << (n)) | ((v) >> (32 - (n)))) 18 | 19 | #define ALIGN(size, alignment) \ 20 | (((size) + ((alignment) - 1)) & ~((alignment) - 1)) 21 | #define ALIGN_PAGE(size) \ 22 | ALIGN(size, 0x4000) 23 | 24 | /* bitfields */ 25 | #define GET_HI(hi, lo) (hi) 26 | #define GET_LO(hi, lo) (lo) 27 | #define GET_MASK(hi, lo) \ 28 | (((1 << ((hi) - (lo) + 1)) - 1) << (lo)) 29 | 30 | #define EXTRACT(value, field) \ 31 | (((value) & field(GET_MASK)) >> field(GET_LO)) 32 | 33 | /* helpers */ 34 | #define X86_CR0_WP (1 << 16) 35 | 36 | static inline __attribute__((always_inline)) 37 | uint64_t read_msr(uint32_t reg) { 38 | uint32_t edx; 39 | uint32_t eax; 40 | __asm__ ("rdmsr" : "=d"(edx), "=a"(eax) : "c"(reg)); 41 | return (((uint64_t)edx) << 32) | (uint64_t)eax; 42 | } 43 | 44 | static inline __attribute__((always_inline)) 45 | uint64_t read_cr0(void) { 46 | uint64_t cr0; 47 | __asm__ ("movq %0, %%cr0" : "=r" (cr0) : : "memory"); 48 | return cr0; 49 | } 50 | 51 | static inline __attribute__((always_inline)) 52 | void write_cr0(uint64_t cr0) { 53 | __asm__ ("movq %%cr0, %0" : : "r" (cr0) : "memory"); 54 | } 55 | 56 | static inline __attribute__((always_inline)) 57 | void cpu_enable_wp(void) 58 | { 59 | uint64_t cr0 = read_cr0(); 60 | write_cr0(cr0 | X86_CR0_WP); 61 | } 62 | 63 | static inline __attribute__((always_inline)) 64 | void cpu_disable_wp(void) 65 | { 66 | uint64_t cr0 = read_cr0(); 67 | write_cr0(cr0 & ~X86_CR0_WP); 68 | } 69 | 70 | static inline __attribute__((always_inline)) 71 | void* curthread(void) 72 | { 73 | uint64_t td; 74 | __asm__ ("movq %0, %%gs:0" : "=r" (td) : : "memory"); 75 | return (void*)td; 76 | } 77 | 78 | #endif /* UTIL_H */ 79 | -------------------------------------------------------------------------------- /tools/dumper/source/md5.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright © 2015 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #ifndef MD5_H 31 | #define MD5_H 32 | 33 | #include "ksdk.h" 34 | 35 | #define MD5_CBLOCK 64 36 | #define MD5_DIGEST_LENGTH 16 37 | #define MD5_LBLOCK MD5_DIGEST_LENGTH/4 38 | 39 | #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) 40 | 41 | #pragma pack(push, 1) 42 | typedef struct _MD5_CTX { 43 | union { 44 | uint8_t b[MD5_DIGEST_LENGTH]; 45 | uint32_t w[MD5_DIGEST_LENGTH/4]; 46 | } s; 47 | union { 48 | uint8_t b[MD5_CBLOCK]; 49 | uint32_t w[MD5_CBLOCK/4]; 50 | uint64_t q[MD5_CBLOCK/8]; 51 | } buf; 52 | uint64_t len; 53 | } MD5_CTX; 54 | #pragma pack(pop) 55 | 56 | #ifdef __cplusplus 57 | extern "C" { 58 | #endif 59 | 60 | void MD5_Init (MD5_CTX*); 61 | void MD5_Update (MD5_CTX*, const void *, uint32_t); 62 | void MD5_Final (void*, MD5_CTX*); 63 | 64 | #ifdef __cplusplus 65 | } 66 | #endif 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /tools/dumper/source/pup_decrypter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2018 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | * 5 | * Based in previous research by: flatz. 6 | */ 7 | 8 | #ifndef PUP_DECRYPTER_H 9 | #define PUP_DECRYPTER_H 10 | 11 | #include "ksdk.h" 12 | 13 | // Format 14 | typedef struct bls_entry_t { 15 | uint32_t block_offset; 16 | uint32_t file_size; 17 | uint32_t reserved[2]; 18 | uint8_t file_name[0x20]; 19 | } bls_entry_t; 20 | 21 | typedef struct bls_header_t { 22 | uint32_t magic; 23 | uint32_t version; 24 | uint32_t flags; 25 | uint32_t entry_count; 26 | uint32_t block_count; 27 | uint32_t reserved[3]; 28 | bls_entry_t entries[0]; 29 | } bls_header_t; 30 | 31 | typedef struct pup_t { 32 | int fd; 33 | char *file_path; 34 | size_t file_size; 35 | size_t entries_size; 36 | /* contents */ 37 | struct bls_header_t header; 38 | struct bls_entry_t *entries; 39 | /* kernel */ 40 | int svc_id; 41 | /* blobs */ 42 | struct blob_t *blobs; 43 | } pup_t; 44 | 45 | /* functions */ 46 | pup_t* pup_open(const char *file); 47 | int pup_verify_header(pup_t *pup); 48 | int pup_decrypt_segments(pup_t *pup); 49 | void pup_close(pup_t *pup); 50 | 51 | #endif /* PUP_DECRYPTER_H */ 52 | -------------------------------------------------------------------------------- /tools/dumper/source/self_decrypter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2018 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | * 5 | * Based in previous tools and research by: fail0verflow, flatz. 6 | */ 7 | 8 | #ifndef SELF_DECRYPTER_H 9 | #define SELF_DECRYPTER_H 10 | 11 | #include "ksdk.h" 12 | 13 | #include "elf32.h" 14 | #include "elf64.h" 15 | 16 | // Format 17 | typedef struct self_entry_t { 18 | uint32_t props; 19 | uint32_t reserved; 20 | uint64_t offset; 21 | uint64_t filesz; 22 | uint64_t memsz; 23 | } self_entry_t; 24 | 25 | typedef struct self_header_t { 26 | uint32_t magic; 27 | uint8_t version; 28 | uint8_t mode; 29 | uint8_t endian; 30 | uint8_t attr; 31 | uint32_t key_type; 32 | uint16_t header_size; 33 | uint16_t meta_size; 34 | uint64_t file_size; 35 | uint16_t num_entries; 36 | uint16_t flags; 37 | uint32_t reserved; 38 | self_entry_t entries[0]; 39 | } self_header_t; 40 | 41 | // Context 42 | struct self_auth_info_t { 43 | uint8_t buf[0x88]; 44 | }; 45 | 46 | typedef struct self_t { 47 | int fd; 48 | char *file_path; 49 | size_t file_size; 50 | size_t entries_size; 51 | size_t data_offset; 52 | size_t data_size; 53 | /* contents */ 54 | struct self_header_t header; 55 | struct self_entry_t *entries; 56 | uint8_t *data; 57 | /* kernel */ 58 | struct self_auth_info_t auth_info; 59 | struct self_context_t *ctx; 60 | int auth_ctx_id; 61 | int ctx_id; 62 | int svc_id; 63 | int verified; 64 | /* blobs */ 65 | struct blob_t *blobs; 66 | } self_t; 67 | 68 | /* functions */ 69 | self_t* self_open(const char *file); 70 | int self_verify_header(self_t *self); 71 | int self_load_segments(self_t *self); 72 | void self_close(self_t *self); 73 | 74 | #endif /* SELF_DECRYPTER_H */ 75 | -------------------------------------------------------------------------------- /tools/dumper/source/self_mapper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2017-2018 Alexandro Sanchez Bach. 3 | * Released under MIT license. Read LICENSE for more details. 4 | * 5 | * Based in previous tools and research by: m0rph3us1987. 6 | */ 7 | 8 | #ifndef SELF_MAPPER_H 9 | #define SELF_MAPPER_H 10 | 11 | #include "ksdk.h" 12 | 13 | /* functions */ 14 | uint8_t* self_decrypt( 15 | uint8_t *self_data, size_t self_size, int self_fd, 16 | size_t *elf_sizep); 17 | 18 | uint8_t* self_decrypt_fd(int fd, 19 | size_t *elf_sizep); 20 | uint8_t* self_decrypt_file(const char *file, 21 | size_t *elf_sizep); 22 | 23 | #endif /* SELF_MAPPER_H */ 24 | -------------------------------------------------------------------------------- /tools/formats/gcn_orbshdr.ksy: -------------------------------------------------------------------------------- 1 | meta: 2 | id: gcn_orbshdr 3 | endian: le 4 | license: CC0-1.0 5 | 6 | instances: 7 | footer: 8 | pos: 80 9 | type: header 10 | 11 | types: 12 | header: 13 | seq: 14 | - id: magic 15 | contents: 'OrbShdr' 16 | - id: unk1 17 | contents: [7] 18 | - id: type2 19 | type: b8 20 | enum: gcn_orbis_type 21 | - id: size 22 | type: u2 23 | 24 | enums: 25 | gcn_orbis_type: 26 | 0x41: gcn_orbis_ps 27 | 0x45: gcn_orbis_vs 28 | -------------------------------------------------------------------------------- /tools/formats/pci.ksy: -------------------------------------------------------------------------------- 1 | meta: 2 | id: pci 3 | endian: le 4 | license: CC0-1.0 5 | 6 | seq: 7 | - id: header 8 | type: header 9 | instances: 10 | capabilities: 11 | pos: header.cap_ptr 12 | type: capability 13 | 14 | types: 15 | header: 16 | seq: 17 | - id: vendor_id 18 | type: u2 19 | - id: device_id 20 | type: u2 21 | - id: command_reg 22 | type: u2 23 | - id: status_reg 24 | type: u2 25 | - id: revision_id 26 | type: u1 27 | - id: class_code 28 | size: 3 29 | - id: cache_line 30 | type: u1 31 | - id: latency_timer 32 | type: u1 33 | - id: header_type 34 | type: u1 35 | - id: bist 36 | type: u1 37 | - id: bar 38 | type: bar 39 | repeat: expr 40 | repeat-expr: 6 41 | - id: cardbus_cis_ptr 42 | type: u4 43 | - id: subsystem_vendor_id 44 | type: u2 45 | - id: subsystem_device_id 46 | type: u2 47 | - id: expansion_rom_addr 48 | type: u4 49 | - id: cap_ptr 50 | type: u1 51 | - size: 7 52 | - id: irq_line 53 | type: u1 54 | - id: irq_pin 55 | type: u1 56 | - id: min_gnt 57 | type: u1 58 | - id: max_gnt 59 | type: u1 60 | bar: 61 | seq: 62 | - id: value 63 | type: u4 64 | instances: 65 | type: 66 | value: value & 1 67 | address: 68 | value: value & 0xFFFFFFFE 69 | doc: Base Address Register 70 | 71 | capability: 72 | seq: 73 | - id: id 74 | type: u1 75 | - id: next 76 | type: u1 77 | instances: 78 | capabilities: 79 | pos: next 80 | type: capability 81 | 82 | -------------------------------------------------------------------------------- /tools/gdb/debug-kernel.gdb: -------------------------------------------------------------------------------- 1 | tui enable 2 | layout split 3 | layout asm 4 | layout regs 5 | target remote localhost:1234 6 | set disassembly-flavor intel 7 | 8 | ########### 9 | # FW 4.55 # 10 | ########### 11 | 12 | define env_orbis_455 13 | #symbol-file orbisys-455.sym 14 | #break btext 15 | end 16 | 17 | ########### 18 | # FW 5.00 # 19 | ########### 20 | 21 | define env_orbis_500 22 | #symbol-file orbisys-500.sym 23 | #break btext 24 | end 25 | 26 | # Continue 27 | env_orbis_500 28 | continue 29 | -------------------------------------------------------------------------------- /tools/gdb/debug-vbios.gdb: -------------------------------------------------------------------------------- 1 | tui enable 2 | layout split 3 | layout asm 4 | layout regs 5 | target remote localhost:1234 6 | set disassembly-flavor intel 7 | 8 | define vc 9 | disable $arg0 10 | stepi 11 | enable $arg0 12 | continue 13 | end 14 | 15 | define atomsi 16 | vc $arg0 17 | print/x $bx 18 | end 19 | 20 | # Continue 21 | hbreak *0xC0003 22 | continue 23 | -------------------------------------------------------------------------------- /tools/generate-blobs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import hashlib 5 | import os 6 | import pathlib 7 | import sys 8 | 9 | def gen_blobs(enc_path, dec_path, out_path): 10 | # Sanity checks 11 | pathlib.Path(out_path).mkdir(parents=True, exist_ok=True) 12 | enc_len = len(os.listdir(enc_path)) 13 | dec_len = len(os.listdir(dec_path)) 14 | out_len = len(os.listdir(out_path)) 15 | assert enc_len != 0 16 | assert dec_len != 0 17 | assert out_len == 0 18 | assert enc_len == dec_len 19 | 20 | for fname in os.listdir(enc_path): 21 | # Read input data 22 | enc_fname = os.path.join(enc_path, fname) 23 | dec_fname = os.path.join(dec_path, fname) 24 | with open(enc_fname, 'rb') as f: 25 | enc_data = f.read() 26 | enc_hash = hashlib.md5(enc_data).hexdigest().upper() 27 | with open(dec_fname, 'rb') as f: 28 | dec_data = f.read() 29 | # Write output data 30 | out_fname = os.path.join(out_path, enc_hash + '.bin') 31 | with open(out_fname, 'wb') as f: 32 | f.write(dec_data) 33 | 34 | def main(): 35 | # Define arguments 36 | parser = argparse.ArgumentParser( 37 | description='Generate blobs compatible with Orbital from pairs of encrypted:decrypted files.') 38 | parser.add_argument('enc', 39 | metavar='path/to/enc', help='path to encrypted blobs', 40 | ) 41 | parser.add_argument('dec', 42 | metavar='path/to/dec', help='path to decrypted blobs', 43 | ) 44 | parser.add_argument('out', 45 | metavar='path/to/out', help='path to output blobs', 46 | ) 47 | # Parse arguments 48 | args = parser.parse_args() 49 | gen_blobs(args.enc, args.dec, args.out) 50 | 51 | 52 | if __name__ == '__main__': 53 | main() 54 | -------------------------------------------------------------------------------- /tools/ghidra/ioctl_probe.py: -------------------------------------------------------------------------------- 1 | #Goes through every reference to "sys_ioctl", and attempts to print the second argument's value. 2 | #@author dtu 3 | #@category PS4 4 | #@keybinding 5 | #@menupath 6 | #@toolbar 7 | 8 | from ghidra.util.task import TaskMonitor 9 | 10 | results = currentProgram.getSymbolTable().getLabelOrFunctionSymbols("sys_ioctl", None) 11 | if len(results) > 0: 12 | ioctl_fun = results[0] 13 | xrefs = ioctl_fun.getReferences(TaskMonitor.DUMMY) 14 | for xref in xrefs: 15 | instr = getInstructionAt(xref.fromAddress) 16 | should_break = False 17 | 18 | while True: 19 | instr = instr.previous 20 | for obj in instr.resultObjects: 21 | if obj.name == "ESI" or obj.name == "RSI": 22 | print xref.fromAddress.toString() + ": " + instr.inputObjects[0].toString() 23 | should_break = True 24 | break 25 | if should_break: 26 | break 27 | else: 28 | print "Could not find symbol 'sys_ioctl'! Did you create it yet?" 29 | -------------------------------------------------------------------------------- /tools/ida/generate_types.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import argparse 4 | import fnmatch 5 | import json 6 | import os 7 | import re 8 | 9 | # Regex patterns 10 | exp_ident = '[A-Za-z_][A-Za-z_0-9]+' 11 | exp_type = '{ei}(?:[\t ]+{ei})*'.format(ei=exp_ident) 12 | 13 | pattern_type = re.compile( 14 | 'typedef\s+({et}[\s\*]+)({ei})'.format( 15 | et=exp_type, ei=exp_ident)) 16 | pattern_func = re.compile( 17 | '({et}[\s\*]+(sce[A-Z][A-Za-z0-9_]+)\s*\([A-Za-z0-9_\*,\s]*\)\s*);'.format( 18 | et=exp_type)) 19 | pattern_attr = re.compile( 20 | '(?:_SCE[0-9A-Z_]+|[0-9A-Z_]+_DECLARE|__inline__)') 21 | 22 | def generate_types(path): 23 | types = {} 24 | # Scan for headers 25 | headers = [] 26 | for root, dirnames, filenames in os.walk(path): 27 | for filename in fnmatch.filter(filenames, '*.h'): 28 | headers.append(os.path.join(root, filename)) 29 | # Process headers 30 | for header in headers: 31 | print(header) 32 | with open(header, 'r', encoding='utf-8') as f: 33 | code = f.read() 34 | matches_type = re.findall(pattern_type, code) 35 | matches_func = re.findall(pattern_func, code) 36 | # Fix function declarations 37 | for mf in matches_func: 38 | func_key = mf[1] 39 | func_val = mf[0].strip() 40 | for mt in matches_type: 41 | type_key = mt[1] 42 | type_val = mt[0].strip() 43 | func_val = func_val.replace(type_key, type_val) 44 | func_val = re.sub(pattern_attr, '', func_val) 45 | func_val = re.sub(r'\s+', ' ', func_val) 46 | func_val = func_val.replace('( ', '(') 47 | func_val = func_val.replace(' )', ')') 48 | types[func_key] = func_val.strip() 49 | return types 50 | 51 | 52 | ### Main ### 53 | 54 | def main(): 55 | # Parse arguments 56 | parser = argparse.ArgumentParser() 57 | 58 | parser.add_argument("--db", type=str, help="path to json database (default: db_types.json)", 59 | metavar="database", default="db_types.json") 60 | parser.add_argument("--update", type=str, help="behavior while updating database (default: keep)", 61 | metavar="update", choices=["keep","overwrite"], default="keep") 62 | parser.add_argument("sdk", type=str, help="path to official/unofficial sdk", 63 | metavar="sdk") 64 | args = parser.parse_args() 65 | # Generate types and merge into existing database, if any 66 | db = {} 67 | if os.path.exists(args.db): 68 | with open(args.db, 'r') as f: 69 | db = json.load(f) 70 | types = generate_types(args.sdk) 71 | for key, val in types.items(): 72 | if args.update == 'overwrite' or key not in db: 73 | db[key] = val 74 | with open(args.db, 'w') as f: 75 | json.dump(db, f, indent=2, sort_keys=True) 76 | 77 | if __name__ == '__main__': 78 | main() 79 | -------------------------------------------------------------------------------- /tools/rai-defines.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import os 3 | import sys 4 | from rai import * 5 | 6 | def should_avoid_expension(reg): 7 | if not reg.fields: 8 | return True 9 | base = reg.fields[0].name[:-1] 10 | for i in xrange(len(reg.fields)): 11 | field = reg.fields[i] 12 | if field.name == base+str(i) and field.hi == field.lo == i: 13 | return True 14 | return False 15 | 16 | def define_reg(addr, reg): 17 | print "#define %-48s 0x%08X" % (reg.name, addr) 18 | if should_avoid_expension(reg): 19 | return 20 | for field in reg.fields: 21 | if (field.hi, field.lo) == (31, 0): 22 | return 23 | macro = " " + field.name + "(M)" 24 | mask = "M(0x%02X,0x%02X)" % (field.hi, field.lo) 25 | print "#define %-46s %8s" % \ 26 | (macro, mask) 27 | 28 | def main(): 29 | if len(sys.argv) <= 1: 30 | print("Generate C/C++ preprocessor #define's for RAI-defined MMIO regs") 31 | print("Requires Python 2.x.") 32 | print("\nUsage: python %s " % os.path.basename(__file__)) 33 | print("\nExample:") 34 | print(" 1. Clone https://github.com/fail0verflow/radeon-tools") 35 | print(" 2. Copy this file to radeon-tools/rai") 36 | print(" 3. Enter that folder and enter:") 37 | print(" - python raiparse.py grammar.rai grammar.pickle") 38 | print(" - python %s GpuF0Reg" % os.path.basename(__file__)) 39 | else: 40 | rai = load_default_rai() 41 | space = sys.argv[1] 42 | space = rai.chip_spaces[space] 43 | for addr, reg in sorted(space.addrs.items()): 44 | define_reg(addr, reg) 45 | 46 | if __name__ == '__main__': 47 | main() 48 | -------------------------------------------------------------------------------- /tools/renderdoc/orbital.cap: -------------------------------------------------------------------------------- 1 | { 2 | "rdocCaptureSettings": 1, 3 | "settings": { 4 | "autoStart": false, 5 | "commandLine": "-bios ./ubios.bin -kernel ./boot.img -drive file=hdd.qcow2 -drive file=fat:sflash/,read-only=off,media=disk -monitor stdio -smp 8 -display orbital -accel hax", 6 | "environment": [ 7 | ], 8 | "executable": "../../bin/qemu-system-ps4.exe", 9 | "inject": false, 10 | "options": { 11 | "allowFullscreen": true, 12 | "allowVSync": true, 13 | "apiValidation": false, 14 | "captureAllCmdLists": false, 15 | "captureCallstacks": false, 16 | "captureCallstacksOnlyDraws": false, 17 | "debugOutputMute": true, 18 | "delayForDebugger": 0, 19 | "hookIntoChildren": false, 20 | "refAllResources": false, 21 | "verifyBufferAccess": false 22 | }, 23 | "workingDir": "" 24 | } 25 | } 26 | --------------------------------------------------------------------------------