You've already forked ps5-linux-loader
mirror of
https://github.com/ps5-linux/ps5-linux-loader.git
synced 2026-04-29 16:42:31 -07:00
initial commit support 3.xx and 4.xx
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
.PHONY: all clean
|
||||
|
||||
ifndef PS5_PAYLOAD_SDK
|
||||
PS5_PAYLOAD_SDK = /opt/ps5-payload-sdk/
|
||||
endif
|
||||
|
||||
include $(PS5_PAYLOAD_SDK)/toolchain/prospero.mk
|
||||
|
||||
BIN := bin/ps5-linux-loader.elf
|
||||
SRC := $(wildcard source/*.c)
|
||||
OBJS := $(SRC:.c=.o)
|
||||
|
||||
# Agregamos los headers de los shellcodes a los CFLAGS para que los encuentre en source/main.c
|
||||
CFLAGS := -std=c23 -Wall -Iinclude -Ishellcode_hypervisor -Ishellcode_kernel
|
||||
LDFLAGS :=
|
||||
|
||||
# Rutas de los headers generados
|
||||
SC_HV_H := shellcode_hypervisor/shellcode_hypervisor.h
|
||||
SC_K_H := shellcode_kernel/shellcode_kernel.h
|
||||
|
||||
# 1. Regla principal: Construir los shellcodes antes que los objetos del main
|
||||
all: $(SC_HV_H) $(SC_K_H) $(BIN)
|
||||
|
||||
# 2. Reglas para disparar el Make en las subcarpetas
|
||||
# Usamos .PHONY de forma indirecta o forzamos la entrada a la carpeta
|
||||
$(SC_HV_H):
|
||||
$(MAKE) -C shellcode_hypervisor
|
||||
|
||||
$(SC_K_H):
|
||||
$(MAKE) -C shellcode_kernel
|
||||
|
||||
# 3. Los objetos dependen de que los headers de los shellcodes existan
|
||||
# Si main.c hace #include "shellcode_hypervisor.h", necesita estos targets
|
||||
$(OBJS): %.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
# 4. Link final
|
||||
$(BIN): $(OBJS)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(OBJS) $(LDFLAGS) -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(BIN) $(OBJS)
|
||||
$(MAKE) -C shellcode_hypervisor clean
|
||||
$(MAKE) -C shellcode_kernel clean
|
||||
@@ -0,0 +1,83 @@
|
||||
# ps5-linux-loader
|
||||
|
||||
This payload let's you boot a Linux kernel on bare metal hardware on the PS5 on firmwares up to 04.51
|
||||
|
||||
Currently firmwares 1.xx and 2.xx are not supported. They will be soon.
|
||||
|
||||
To do so, it uses a disclosed vulnerability that gives access to Trusted Memory Regions (TMRs).
|
||||
|
||||
The process to boot Linux is divided in 3 stages:
|
||||
|
||||
- Payload on Prospero OS that disables HV protections to install a shellcode in Kernel mode to be loader on system wake-up and loads Linux boot bins on memory.
|
||||
- Kernel shellcode that disables HV protections and patches "VMEXIT_HANDLER" to install identity mapping and jump to HV shellcode.
|
||||
- Hypervisor shellcode (real bare metal) that loads the required structure and boots the Linux kernel.
|
||||
|
||||
PLEASE USE AT YOUR OWN RISK. IT MAY DAMAGE YOUR CONSOLE TURNING IT UNREPAIRABLE.
|
||||
|
||||
## Credits
|
||||
|
||||
[theflow](https://github.com/TheOfficialFloW): Linux kernel patches, main boot config and boot strategy
|
||||
|
||||
[c0w](https://github.com/c0w-ar): Loader code and kernel/hv shellcodes
|
||||
|
||||
[fail0verflow](https://github.com/fail0verflow): HV defeat vulnerability (https://github.com/fail0verflow/prosperous)
|
||||
|
||||
[flatz](github.com/flatz): HV defeat vulnerability (https://gist.github.com/flatz/620ddda6d64acca6d1c990dc3080ac0e)
|
||||
|
||||
[cragson](https://github.com/cragson): HV defeat implementation for <= 04.51 on PS5 HEN (https://github.com/cragson/ps5-hen)
|
||||
|
||||
[john-tornblom](https://github.com/john-tornblom): PS5 SDK (https://github.com/ps5-payload-dev/sdk)
|
||||
|
||||
[echostretch](https://github.com/echostretch): Offsets and testing
|
||||
|
||||
## Own compilation
|
||||
|
||||
First, install the [ps5-payload-sdk](https://github.com/ps5-payload-dev/sdk)
|
||||
|
||||
Second, clone this repository and make
|
||||
|
||||
```
|
||||
git clone git@github.com:c0w-ar/ps5-linux-loader.git
|
||||
|
||||
cd ps5-linux-loader
|
||||
|
||||
make
|
||||
```
|
||||
## Prework
|
||||
|
||||
To be able to boot linux, you first have to create a fresh install image of your desired distribution (Ubuntu recommended) on an external USB drive (SSD recommended).
|
||||
|
||||
You can use any live CD / USB to install to the external drive. It's recommended that you take note of your partition UUID to use it on the boot command.
|
||||
|
||||
Recommended boot command:
|
||||
```
|
||||
root=UUID={your-partition-hash} rw rootwait console=ttyTitania0 console=tty0 video=DP-1:1920x1080@60 mitigations=off idle=halt pci=pcie_bus_perf
|
||||
```
|
||||
|
||||
## How to Use
|
||||
|
||||
Place the bzImage and initrd.img files on the folder "PS5/Linux/" on your USB drive.
|
||||
|
||||
If you wish to customize the Video Ram (vram) or Boot Command you can optionally add the files "vram.txt" and "cmdline.txt".
|
||||
|
||||
```
|
||||
USB0 Root
|
||||
└── 📁 PS5
|
||||
└── 📁 Linux
|
||||
└── 📄 bzImage
|
||||
└── 📄 initrd.img
|
||||
└── 📄 vram.txt (hex string)
|
||||
└── 📄 cmdline.txt (custom boot command)
|
||||
```
|
||||
|
||||
Send the payload
|
||||
|
||||
```sh
|
||||
socat -t 99999 - TCP:YOUR_PS5_IP:9021 < ps5-linux-loader.elf
|
||||
```
|
||||
|
||||
Wait until you see the message that is time to put the system to sleep.
|
||||
|
||||
When the orange light stop blinking and stays on, you can wake up your console and the shellcodes will be executed.
|
||||
|
||||
You should get the Linux kernel booted and an available console on the UART Titania.
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#define PAGE_SIZE 0x4000ULL
|
||||
|
||||
// This is used to allocate resources for HV shellcode and Linux boot
|
||||
#define cave 0x100000000ULL
|
||||
#define cave_hv_paging cave
|
||||
#define cave_hv_code \
|
||||
cave_hv_paging + 0x3000ULL // Leave space for 3 pages but we only use 2 for
|
||||
// 1GB 1:1 mapping
|
||||
#define cave_linux_files cave_hv_code + 0x2000ULL
|
||||
#define cave_linux_info cave_linux_files
|
||||
#define cave_bzImage cave_linux_info + PAGE_SIZE
|
||||
// #define cave_initrd // Allocated dynamically after bzImage
|
||||
|
||||
#define hv_base_rsp (cave + 0x10000000ULL)
|
||||
#define hv_stack_size 0x1000ULL
|
||||
|
||||
// This is used as transitional storage from ProsperoOS to Kernel shellcode
|
||||
#define kernel_cave_files 0xFFFF800000000000
|
||||
#define kernel_cave_linux_info kernel_cave_files
|
||||
#define kernel_cave_bzImage kernel_cave_linux_info + PAGE_SIZE
|
||||
// #define kernel_cave_initrd // Allocated dynamically after bzImage
|
||||
|
||||
// Linux boot config
|
||||
#define VRAM_SIZE (512ULL * 1024 * 1024)
|
||||
#define CMD_LINE \
|
||||
"root=/dev/sda2 rw rootwait console=ttyTitania0 console=tty0 " \
|
||||
"video=DP-1:1920x1080@60 mitigations=off idle=halt pci=pcie_bus_perf"
|
||||
|
||||
#define DEBUG 0 // Toggle to 0 to disable logs
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
/*** Source: ps5-hen by cragson ***/
|
||||
|
||||
#ifndef GPU_H
|
||||
#define GPU_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define GPU_PDE_VALID_BIT 0
|
||||
#define GPU_PDE_IS_PTE_BIT 54
|
||||
#define GPU_PDE_TF_BIT 56
|
||||
#define GPU_PDE_BLOCK_FRAG_BIT 59
|
||||
#define GPU_PDE_ADDR_MASK 0x0000FFFFFFFFFFC0ULL
|
||||
|
||||
#define PROT_GPU_READ 0x10
|
||||
#define PROT_GPU_WRITE 0x20
|
||||
#define MAP_NO_COALESCE 0x00400000
|
||||
|
||||
#define GPU_SUBMIT_IOCTL 0xC0108102
|
||||
|
||||
#define PM4_TYPE3 3
|
||||
#define PM4_SHADER_COMPUTE 1
|
||||
#define PM4_OPCODE_DMA_DATA 0x50
|
||||
#define PM4_OPCODE_INDIRECT_BUF 0x3F
|
||||
|
||||
struct gpu_kernel_offsets {
|
||||
uint64_t proc_vmspace; // proc->p_vmspace offset
|
||||
uint64_t vmspace_vm_vmid; // vmspace->vm_vmid offset
|
||||
uint64_t data_base_gvmspace; // offset from kernel data base to gvmspace array
|
||||
uint64_t sizeof_gvmspace; // size of each gvmspace entry
|
||||
uint64_t gvmspace_page_dir_va; // gvmspace->page_dir_va offset (GPU PDB2)
|
||||
uint64_t gvmspace_size; // gvmspace->size offset
|
||||
uint64_t gvmspace_start_va; // gvmspace->start_va offset
|
||||
};
|
||||
|
||||
struct gpu_ctx {
|
||||
int fd; // /dev/gc file descriptor
|
||||
int initialized; // 1 if gpu_init() succeeded
|
||||
|
||||
uint64_t victim_va; // CPU VA of victim buffer (GPU PTE remapped)
|
||||
uint64_t transfer_va; // CPU VA of transfer/staging buffer
|
||||
uint64_t cmd_va; // CPU VA of PM4 command buffer
|
||||
|
||||
uint64_t victim_real_pa; // original physical address of victim buffer
|
||||
uint64_t victim_ptbe_va; // kernel VA of the GPU PTE for victim buffer
|
||||
uint64_t cleared_ptbe; // GPU PTE with physical address cleared (template)
|
||||
uint64_t page_size; // GPU page size for victim allocation (should be 2MB)
|
||||
uint64_t dmem_size; // allocation size (2MB)
|
||||
};
|
||||
|
||||
void gpu_set_offsets(struct gpu_kernel_offsets *offsets);
|
||||
|
||||
int gpu_init(void);
|
||||
int gpu_init_internal(void);
|
||||
|
||||
int gpu_test(void);
|
||||
|
||||
int gpu_read_phys(uint64_t phys_addr, void *out_buf, uint32_t size);
|
||||
uint8_t gpu_read_phys1(uint64_t phys_addr);
|
||||
uint32_t gpu_read_phys4(uint64_t phys_addr);
|
||||
uint64_t gpu_read_phys8(uint64_t phys_addr);
|
||||
|
||||
int gpu_write_phys(uint64_t phys_addr, const void *in_buf, uint32_t size);
|
||||
void gpu_write_phys4(uint64_t phys_addr, uint32_t value);
|
||||
void gpu_write_phys8(uint64_t phys_addr, uint64_t value);
|
||||
|
||||
void gpu_cleanup(void);
|
||||
|
||||
struct gpu_ctx *gpu_get_ctx(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef HV_DEFEAT_H
|
||||
#define HV_DEFEAT_H
|
||||
|
||||
#include "iommu.h"
|
||||
#include <stdint.h>
|
||||
|
||||
int hv_defeat(void);
|
||||
int stage1_tmr_relax(void);
|
||||
int stage2_find_vmcbs(void);
|
||||
uint64_t get_vmcb(int core);
|
||||
int iommu_selftest(void);
|
||||
int stage3_patch_vmcbs(void);
|
||||
int stage4_force_vmcb_reload(void);
|
||||
int stage5_remove_xotext(void);
|
||||
int stage6_kernel_pmap_invalidate_all(void);
|
||||
int stage7_install_kexec(void);
|
||||
int kexec(uint64_t fptr);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
/*** Source: ps5-hen by cragson ***/
|
||||
|
||||
#ifndef IOMMU_H
|
||||
#define IOMMU_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Command buffer MMIO offsets
|
||||
#define IOMMU_MMIO_CB_HEAD 0xa000
|
||||
#define IOMMU_MMIO_CB_TAIL 0xa008
|
||||
|
||||
// Queue constants
|
||||
#define IOMMU_CB_SIZE 0x2000
|
||||
#define IOMMU_CB_MASK (IOMMU_CB_SIZE - 1)
|
||||
#define IOMMU_CMD_ENTRY_SIZE 0x10
|
||||
|
||||
// IOMMU softc field offsets
|
||||
#define IOMMU_SC_MMIO_VA 0x40
|
||||
#define IOMMU_SC_CB2_PTR 0x78
|
||||
#define IOMMU_SC_CB3_PTR 0x80
|
||||
#define IOMMU_SC_EB_PTR 0x60b90
|
||||
|
||||
typedef struct _iommu_ctx {
|
||||
uint64_t cb2_base; // kernel VA of command buffer 2 (hv terminology)
|
||||
uint64_t cb3_base; // kernel VA of command buffer 3 (hv terminology)
|
||||
uint64_t eb_base; // kernel VA of event buffer
|
||||
uint64_t mmio_va; // DMAP VA of IOMMU MMIO base
|
||||
} iommu_ctx;
|
||||
|
||||
extern iommu_ctx iommu_store;
|
||||
extern iommu_ctx *iommu;
|
||||
|
||||
int iommu_init(void);
|
||||
|
||||
// Submit a single 16-byte command and wait for completion
|
||||
void iommu_submit_cmd(const void *cmd);
|
||||
// Write 8 bytes to a physical address using IOMMU completion wait store
|
||||
void iommu_write8_pa(uint64_t pa, uint64_t val);
|
||||
|
||||
// Write 4 bytes to a physical address
|
||||
void iommu_write4_pa(uint64_t pa, uint32_t val);
|
||||
|
||||
// Write arbitrary length to a physical address in 8-byte chunks
|
||||
void iommu_write_pa(uint64_t pa, const void *data, uint32_t len);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "utils.h"
|
||||
#include <stdint.h>
|
||||
|
||||
static uint64_t alloc_page(void);
|
||||
static void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa,
|
||||
int bits);
|
||||
void pte_store(uintptr_t ptep, uint64_t pte);
|
||||
static int read_file(const char *path, void *buf, size_t bufsize);
|
||||
static void trim_newline(char *s);
|
||||
static size_t fetch_file(int port, void *buf, size_t bufsize);
|
||||
int fetch_linux(struct linux_info *info);
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
int main(void);
|
||||
int setup_env(void);
|
||||
int prepare_resume(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifndef OFFSETS_H
|
||||
#define OFFSETS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct _offset_list {
|
||||
uint64_t PMAP_STORE;
|
||||
uint64_t HV_BSS_OFF; // Needed for 1.xx and 2.xx
|
||||
uint64_t HV_VCPU; // Needed for 1.xx and 2.xx
|
||||
uint64_t HV_VCPU_CPUID; // Needed for 1.xx and 2.xx
|
||||
uint64_t HV_VCPU_ARRAY_OFF; // Needed for 1.xx and 2.xx
|
||||
uint64_t HV_VCPU_STRIDE; // Needed for 1.xx and 2.xx
|
||||
uint64_t HV_VCPU_VMCB_PTR; // Needed for 1.xx and 2.xx
|
||||
uint64_t KERNEL_CODE_CAVE;
|
||||
uint64_t KERNEL_DATA_CAVE;
|
||||
uint64_t IOMMU_SOFTC;
|
||||
uint64_t VMSPACE_VM_VMID;
|
||||
uint64_t VMSPACE_VM_PMAP;
|
||||
uint64_t PMAP_PM_PML4;
|
||||
uint64_t PMAP_PM_CR3;
|
||||
uint64_t DATA_BASE_GVMSPACE;
|
||||
uint64_t HOOK_ACPI_WAKEUP_MACHDEP;
|
||||
uint64_t FUN_PRINTF;
|
||||
uint64_t FUN_VA_TO_PA;
|
||||
uint64_t FUN_HV_IOMMU_SET_BUFFERS;
|
||||
uint64_t FUN_HV_IOMM_WAIT_COMPLETION;
|
||||
uint64_t FUN_SMP_RENDEZVOUS;
|
||||
uint64_t FUN_SMP_NO_RENDEVOUS_BARRIER;
|
||||
uint64_t HV_HANDLE_VMEXIT_PA;
|
||||
uint64_t HV_CODE_CAVE_PA;
|
||||
uint64_t HV_UART_OVERRIDE_PA;
|
||||
uint64_t G_VBIOS;
|
||||
uint64_t FUN_TRANSMITTER_CONTROL;
|
||||
uint64_t FUN_MP3_INITIALIZE;
|
||||
uint64_t FUN_MP3_INVOKE;
|
||||
uint64_t KERNEL_UART_OVERRIDE;
|
||||
uint64_t KERNEL_DEBUG_PATCH;
|
||||
uint64_t KERNEL_CFI_CHECK;
|
||||
} offset_list;
|
||||
|
||||
extern offset_list off_0300;
|
||||
extern offset_list off_0310;
|
||||
extern offset_list off_0320;
|
||||
extern offset_list off_0321;
|
||||
extern offset_list off_0400;
|
||||
extern offset_list off_0402;
|
||||
extern offset_list off_0403;
|
||||
extern offset_list off_0450;
|
||||
extern offset_list off_0451;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef TMR_H
|
||||
#define TMR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define ECAM_B0D18F2 dmap + (0xF0000000ULL + 0x18ULL * 0x8000 + 2 * 0x1000)
|
||||
#define TMR_INDEX_OFF 0x80
|
||||
#define TMR_DATA_OFF 0x84
|
||||
|
||||
#define TMR_BASE(n) ((n) * 0x10 + 0x00)
|
||||
#define TMR_LIMIT(n) ((n) * 0x10 + 0x04)
|
||||
#define TMR_CONFIG(n) ((n) * 0x10 + 0x08)
|
||||
#define TMR_REQUESTORS(n) ((n) * 0x10 + 0x0C)
|
||||
#define TMR_CFG_PERMISSIVE 0x3F07
|
||||
|
||||
uint32_t tmr_read(uint32_t addr);
|
||||
void tmr_write(uint32_t addr, uint32_t val);
|
||||
|
||||
#endif
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include "offsets.h"
|
||||
#include <ps5/kernel.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
int sceKernelGetCurrentCpu();
|
||||
int sceKernelSendNotificationRequest(int, void *, size_t, int);
|
||||
|
||||
typedef struct _sysent {
|
||||
uint32_t n_arg;
|
||||
uint32_t pad;
|
||||
uint64_t sy_call;
|
||||
uint64_t sy_auevent;
|
||||
uint64_t sy_systrace_args;
|
||||
uint32_t sy_entry;
|
||||
uint32_t sy_return;
|
||||
uint32_t sy_flags;
|
||||
uint32_t sy_thrcnt;
|
||||
} sysent;
|
||||
|
||||
typedef struct __flat_pmap {
|
||||
uint64_t mtx_name_ptr;
|
||||
uint64_t mtx_flags;
|
||||
uint64_t mtx_data;
|
||||
uint64_t mtx_lock;
|
||||
uint64_t pm_pml4;
|
||||
uint64_t pm_cr3;
|
||||
} flat_pmap;
|
||||
|
||||
struct linux_info {
|
||||
uintptr_t bzimage;
|
||||
size_t bzimage_size;
|
||||
uintptr_t initrd;
|
||||
size_t initrd_size;
|
||||
size_t vram_size;
|
||||
char cmdline[2048];
|
||||
uintptr_t linux_info; // PA of linux_info
|
||||
};
|
||||
|
||||
/** These vars are global for the payload to simplify things */
|
||||
extern offset_list env_offset; // Defined on utils.c
|
||||
extern uint64_t ktext; // Defined on utils.c
|
||||
extern uint64_t kdata; // Defined on utils.c
|
||||
extern uint64_t dmap; // Defined on utils.c
|
||||
extern uint64_t cr3; // Defined on utils.c
|
||||
extern uint32_t fw; // Defined on utils.c
|
||||
extern uint64_t vmcb_pa[16]; // Defined on hv_defeat.c
|
||||
extern struct linux_info linux_i; // Declared on main.c
|
||||
|
||||
static inline void kwrite(uint64_t ka, void *src, uint64_t len) {
|
||||
kernel_copyin(src, ka, len);
|
||||
}
|
||||
|
||||
static inline void kwrite64(uint64_t dst, uint64_t val) {
|
||||
kernel_copyin(&val, dst, 8);
|
||||
}
|
||||
|
||||
static inline void kwrite32(uint64_t dst, uint32_t val) {
|
||||
kernel_copyin(&val, dst, 4);
|
||||
}
|
||||
|
||||
static inline void kwrite8(uint64_t dst, uint8_t val) {
|
||||
kernel_copyin(&val, dst, 1);
|
||||
}
|
||||
|
||||
static inline void kread(uint64_t ka, void *dst, uint64_t len) {
|
||||
kernel_copyout(ka, dst, len);
|
||||
}
|
||||
|
||||
static inline uint64_t kread64(uint64_t src) {
|
||||
uint64_t val;
|
||||
kernel_copyout(src, &val, 8);
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint32_t kread32(uint64_t src) {
|
||||
uint32_t val;
|
||||
kernel_copyout(src, &val, 4);
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint8_t kread8(uint64_t src) {
|
||||
uint8_t val;
|
||||
kernel_copyout(src, &val, 1);
|
||||
return val;
|
||||
}
|
||||
|
||||
int set_offsets(void);
|
||||
int init_global_vars(void);
|
||||
uint64_t get_offset_va(uint64_t offset);
|
||||
|
||||
// Defines for Page management
|
||||
#define ALIGN_UP(size, align) (((size) + (align) - 1) & ~((align) - 1))
|
||||
#define INKERNEL(va) (va & 0xFFFF000000000000)
|
||||
|
||||
enum page_bits {
|
||||
P = 0,
|
||||
RW,
|
||||
US,
|
||||
PWT,
|
||||
PCD,
|
||||
A,
|
||||
D,
|
||||
PS,
|
||||
G,
|
||||
XO = 58,
|
||||
PK = 59,
|
||||
NX = 63
|
||||
};
|
||||
|
||||
#define PG_B_P (1ULL << P)
|
||||
#define PG_B_RW (1ULL << RW)
|
||||
#define PAGE_P(x) (x & (1ULL << P))
|
||||
#define PAGE_RW(x) (x & (1ULL << RW))
|
||||
#define PAGE_PS(x) (x & (1ULL << PS))
|
||||
#define PAGE_XO(x) (x & (1ULL << XO))
|
||||
#define PAGE_CLEAR_XO(x) (x &= ~(1ULL << XO))
|
||||
#define PAGE_CLEAR_G(x) (x &= ~(1ULL << G))
|
||||
#define PAGE_SET_RW(x) (x |= (1ULL << RW))
|
||||
#define PAGE_PA(x) (x & 0x000FFFFFFFFFF000ULL)
|
||||
#define P_SIZE(l) ((l == 1) ? (1ULL << 30) : (1ULL << 21))
|
||||
|
||||
#define pmap_pml4e_index(va) ((va >> 39) & 0x1FF)
|
||||
#define pmap_pdpe_index(va) ((va >> 30) & 0x1FF)
|
||||
#define pmap_pde_index(va) ((va >> 21) & 0x1FF)
|
||||
#define pmap_pte_index(va) ((va >> 12) & 0x1FF)
|
||||
|
||||
uint64_t va_to_pa_user(uint64_t va);
|
||||
uint64_t va_to_pa_kernel(uint64_t va);
|
||||
uint64_t va_to_pa_custom(uint64_t va, uint64_t cr3_custom);
|
||||
uint64_t pa_to_dmap(uint64_t pa);
|
||||
void page_chain_set_rw(uint64_t va);
|
||||
uint64_t page_remove_global(uint64_t va);
|
||||
|
||||
uint64_t getpmap(uint64_t proc_ptr);
|
||||
uint64_t get_pml4(uint64_t pmap);
|
||||
|
||||
int pin_to_core(int n);
|
||||
int pin_to_first_available_core(void);
|
||||
void unpin(void);
|
||||
static inline void notify(uint8_t *msg) {
|
||||
struct {
|
||||
char pad[45];
|
||||
char msg[3075];
|
||||
} req;
|
||||
uint64_t len =
|
||||
strlen(msg) < (sizeof(req.msg) - 1) ? strlen(msg) : (sizeof(req.msg) - 1);
|
||||
memcpy(req.msg, msg, len);
|
||||
sceKernelSendNotificationRequest(0, &req, sizeof(req), 0);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#define DEBUG_PRINT(fmt, ...) printf(fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_PRINT(fmt, ...)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
ifndef PS5_PAYLOAD_SDK
|
||||
PS5_PAYLOAD_SDK = /opt/ps5-payload-sdk/
|
||||
endif
|
||||
|
||||
# 1. Variables
|
||||
CC = gcc
|
||||
LD = ld
|
||||
CFLAGS = -O2 -fno-stack-protector -ffreestanding -nostdlib -fcf-protection=none -I$(PS5_PAYLOAD_SDK)/target/include
|
||||
LDFLAGS = -T linker.ld
|
||||
TARGET = shellcode_hypervisor.elf
|
||||
TEXT_BIN = shellcode_hypervisor.bin
|
||||
dump = shellcode_hypervisor.h
|
||||
|
||||
SRC = main.c utils.c boot_linux.c
|
||||
OBJ = $(SRC:.c=.o)
|
||||
|
||||
all: $(dump)
|
||||
|
||||
$(TARGET): $(OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) -o $(TARGET)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(TEXT_BIN): $(TARGET)
|
||||
objcopy -O binary -j .shell_code $(TARGET) $(TEXT_BIN)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) $(TARGET) $(TEXT_BIN) $(dump)
|
||||
|
||||
$(dump): $(TEXT_BIN)
|
||||
python3 bin_to_c_hypervisor.py $(TEXT_BIN)
|
||||
@@ -0,0 +1,46 @@
|
||||
import sys
|
||||
import os
|
||||
|
||||
def create_shellcode_header(input_file):
|
||||
if not os.path.exists(input_file):
|
||||
print(f"Error: {input_file} not found.")
|
||||
return
|
||||
|
||||
# Read binary data_text
|
||||
with open(input_file, "rb") as f:
|
||||
data_text = f.read()
|
||||
|
||||
# Hardcoded output name
|
||||
output_name = "shellcode_hypervisor.h"
|
||||
array_name = "shellcode_hypervisor"
|
||||
|
||||
with open(output_name, "w") as f:
|
||||
f.write(f"// Generated from {input_file}\n")
|
||||
f.write(f"#ifndef SHELLCODE_HV_H\n")
|
||||
f.write(f"#define SHELLCODE_HV_H\n\n")
|
||||
f.write(f"#include <unistd.h>\n\n")
|
||||
|
||||
f.write(f"uint8_t {array_name}[] = {{\n ")
|
||||
|
||||
for i, byte in enumerate(data_text):
|
||||
f.write(f"0x{byte:02X}")
|
||||
|
||||
if i < len(data_text) - 1:
|
||||
f.write(", ")
|
||||
|
||||
# New line every 12 bytes
|
||||
if (i + 1) % 12 == 0:
|
||||
f.write("\n ")
|
||||
|
||||
f.write(f"\n}};\n\n")
|
||||
f.write(f"uint64_t {array_name}_len = {len(data_text)};\n\n")
|
||||
|
||||
f.write(f"#endif // SHELLCODE_HV_H\n")
|
||||
|
||||
print(f"Done! Created {output_name} ({len(data_text)} bytes)")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python bin_to_c_hypervisor.py <shellcode.bin>")
|
||||
else:
|
||||
create_shellcode_header(sys.argv[1])
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "boot_linux.h"
|
||||
#include "../include/config.h"
|
||||
#include "linux.h"
|
||||
#include "utils.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct linux_info {
|
||||
uintptr_t bzimage;
|
||||
size_t bzimage_size;
|
||||
uintptr_t initrd;
|
||||
size_t initrd_size;
|
||||
size_t vram_size;
|
||||
char cmdline[2048];
|
||||
};
|
||||
|
||||
static struct linux_info info;
|
||||
|
||||
static volatile int exited_cpus = 0;
|
||||
|
||||
static void configure_vram(uint64_t fb_start, uint64_t vram_start,
|
||||
uint64_t vram_size) {
|
||||
uint64_t vram_end = vram_start + vram_size - 1;
|
||||
uint64_t fb_top = fb_start + vram_size - 1;
|
||||
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + RCC_CONFIG_MEMSIZE) = vram_size >> 20;
|
||||
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + GCMC_VM_FB_OFFSET) = vram_start >> 24;
|
||||
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + GCMC_VM_LOCAL_HBM_ADDRESS_START) =
|
||||
vram_start >> 24;
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + GCMC_VM_LOCAL_HBM_ADDRESS_END) =
|
||||
vram_end >> 24;
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + GCMC_VM_FB_LOCATION_BASE) = fb_start >> 24;
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + GCMC_VM_FB_LOCATION_TOP) = fb_top >> 24;
|
||||
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + MMMC_VM_FB_OFFSET) = vram_start >> 24;
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + MMMC_VM_LOCAL_HBM_ADDRESS_START) =
|
||||
vram_start >> 24;
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + MMMC_VM_LOCAL_HBM_ADDRESS_END) =
|
||||
vram_end >> 24;
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + MMMC_VM_FB_LOCATION_BASE) = fb_start >> 24;
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + MMMC_VM_FB_LOCATION_TOP) = fb_top >> 24;
|
||||
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + MMHUBBUB_WHITELIST_BASE_ADDR_0) =
|
||||
vram_start >> 12;
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + MMHUBBUB_WHITELIST_TOP_ADDR_0) =
|
||||
vram_end >> 12;
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + DCHUBBUB_WHITELIST_BASE_ADDR_0) =
|
||||
vram_start >> 12;
|
||||
*(uint32_t *)(AMDGPU_MMIO_BASE + DCHUBBUB_WHITELIST_TOP_ADDR_0) =
|
||||
vram_end >> 12;
|
||||
}
|
||||
|
||||
static void append_e820_table(struct boot_params *bp, uint64_t start,
|
||||
uint64_t end, uint32_t type) {
|
||||
uint8_t idx = bp->e820_entries;
|
||||
bp->e820_table[idx].addr = start;
|
||||
bp->e820_table[idx].size = end - start;
|
||||
bp->e820_table[idx].type = type;
|
||||
bp->e820_entries++;
|
||||
}
|
||||
|
||||
static void e820_memory_setup(struct boot_params *bp) {
|
||||
append_e820_table(bp, 0x000000000, 0x000001000, E820_TYPE_RESERVED);
|
||||
append_e820_table(bp, 0x000001000, 0x000070000, E820_TYPE_RAM);
|
||||
append_e820_table(bp, 0x000070000, 0x0000a0000, E820_TYPE_RESERVED);
|
||||
append_e820_table(bp, 0x0000a0000, 0x0000c0000, E820_TYPE_RESERVED);
|
||||
append_e820_table(bp, 0x0000c0000, 0x000100000, E820_TYPE_RESERVED); // VBIOS
|
||||
append_e820_table(bp, 0x000100000, 0x03fffc000, E820_TYPE_RAM);
|
||||
append_e820_table(bp, 0x03fffc000, 0x040000000, E820_TYPE_RESERVED);
|
||||
append_e820_table(bp, 0x040000000, 0x060000000, E820_TYPE_RAM);
|
||||
append_e820_table(bp, 0x060000000, 0x060800000, E820_TYPE_RESERVED); // MP4
|
||||
append_e820_table(bp, 0x060800000, 0x060c00000, E820_TYPE_RESERVED); // VCN FW
|
||||
append_e820_table(bp, 0x060c00000, 0x062800000, E820_TYPE_RAM);
|
||||
append_e820_table(bp, 0x062800000, 0x064800000, E820_TYPE_RESERVED); // HV
|
||||
append_e820_table(bp, 0x064800000, 0x064829000, E820_TYPE_RESERVED); // MP3
|
||||
append_e820_table(bp, 0x064829000, 0x07f9d0000, E820_TYPE_RAM);
|
||||
append_e820_table(bp, 0x07f9d0000, 0x07fd5f000, E820_TYPE_RESERVED);
|
||||
append_e820_table(bp, 0x07fd5f000, 0x07fd63000, E820_TYPE_RESERVED);
|
||||
append_e820_table(bp, 0x07fd63000, 0x07fd67000, E820_TYPE_RESERVED);
|
||||
append_e820_table(bp, 0x07fd67000, 0x07fd6f000, E820_TYPE_NVS);
|
||||
append_e820_table(bp, 0x07fd6f000, 0x07fd8f000, E820_TYPE_ACPI);
|
||||
append_e820_table(bp, 0x07fd8f000, 0x07fd90000, E820_TYPE_RESERVED);
|
||||
append_e820_table(bp, 0x07fd90000, 0x080000000, E820_TYPE_RESERVED);
|
||||
append_e820_table(bp, 0x080000000, 0x0c4400000, E820_TYPE_RESERVED);
|
||||
append_e820_table(bp, 0x0d0000000, 0x0e0700000, E820_TYPE_RESERVED);
|
||||
append_e820_table(bp, 0x0f0000000, 0x0f8000000, E820_TYPE_RESERVED);
|
||||
append_e820_table(bp, 0x100000000, VRAM_BASE, E820_TYPE_RAM);
|
||||
append_e820_table(bp, VRAM_BASE, 0x470000000, E820_TYPE_RESERVED); // VRAM
|
||||
append_e820_table(bp, 0x470000000, 0x47f300000, E820_TYPE_RAM);
|
||||
append_e820_table(bp, 0x47f300000, 0x480000000, E820_TYPE_RESERVED);
|
||||
}
|
||||
|
||||
void boot_linux(void) {
|
||||
uintptr_t kernel_pa = 0x100000;
|
||||
uintptr_t setup_pa = 0x10000;
|
||||
uintptr_t cmdline_pa = 0x20000;
|
||||
|
||||
struct boot_params *bzimage_bp = (struct boot_params *)info.bzimage;
|
||||
|
||||
struct boot_params *bp = (struct boot_params *)setup_pa;
|
||||
struct setup_header *shdr = &bp->hdr;
|
||||
|
||||
memset(bp, 0, sizeof(struct boot_params));
|
||||
|
||||
memcpy(shdr, &bzimage_bp->hdr, sizeof(struct setup_header));
|
||||
|
||||
e820_memory_setup(bp);
|
||||
|
||||
shdr->hardware_subarch = X86_SUBARCH_PS5;
|
||||
shdr->type_of_loader = 0xff;
|
||||
shdr->cmd_line_ptr = cmdline_pa;
|
||||
shdr->ramdisk_image = info.initrd & 0xffffffff;
|
||||
shdr->ramdisk_size = info.initrd_size & 0xffffffff;
|
||||
bp->ext_ramdisk_image = info.initrd >> 32;
|
||||
bp->ext_ramdisk_size = info.initrd_size >> 32;
|
||||
bp->acpi_rsdp_addr = ACPI_RSDP_ADDRESS;
|
||||
|
||||
strcpy((char *)cmdline_pa, info.cmdline);
|
||||
|
||||
size_t setup_size = (shdr->setup_sects + 1) * 512;
|
||||
size_t kernel_size = shdr->syssize * 16;
|
||||
|
||||
memcpy((void *)kernel_pa, (void *)(info.bzimage + setup_size), kernel_size);
|
||||
|
||||
// printf("This is kernel_pa: "); print_val64(kernel_pa); printf("\n");
|
||||
void (*startup_64)(uint64_t physaddr, struct boot_params *bp) =
|
||||
(void *)(kernel_pa + 0x200);
|
||||
startup_64(kernel_pa, bp);
|
||||
}
|
||||
|
||||
void entry(void) {
|
||||
|
||||
disable_intr();
|
||||
|
||||
// Set global interrupt flag.
|
||||
__asm__ volatile("stgi\n");
|
||||
|
||||
// Clear SVM flag.
|
||||
wrmsr(MSR_EFER, rdmsr(MSR_EFER) & ~EFER_SVM);
|
||||
|
||||
// Disable INIT redirection.
|
||||
wrmsr(MSR_VM_CR, rdmsr(MSR_VM_CR) & ~VM_CR_R_INIT);
|
||||
|
||||
// Clean up mtrr.
|
||||
wrmsr(MSR_MTRR4kBase + 0, 0);
|
||||
|
||||
wrmsr(MSR_MTRR4kBase + 1, 0);
|
||||
|
||||
wrmsr(MSR_MTRRVarBase + 7 * 2 + 1, 0);
|
||||
|
||||
atomic_add_32(&exited_cpus, 1);
|
||||
|
||||
while (atomic_cmpset_32(&exited_cpus, MAXCPU, MAXCPU) == 0)
|
||||
;
|
||||
|
||||
if (get_cpu() != 0) {
|
||||
while (1) {
|
||||
halt();
|
||||
}
|
||||
}
|
||||
|
||||
// Disable IOMMU.
|
||||
*(volatile uint64_t *)0xfdd80018 &= ~1;
|
||||
|
||||
memcpy(&info, (void *)(cave_linux_info), sizeof(struct linux_info));
|
||||
|
||||
configure_vram(FB_BASE, VRAM_BASE, info.vram_size);
|
||||
|
||||
printf("[*] Booting Linux in bare metal...\n");
|
||||
boot_linux();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
#define MSR_EFER 0xc0000080
|
||||
#define EFER_SVM (1ULL << 12) // Bit 12: Secure Virtual Machine Enable
|
||||
|
||||
// // Virtual Machine Control Register (VM_CR)
|
||||
#define MSR_VM_CR 0xc0010114
|
||||
#define VM_CR_R_INIT (1ULL << 1) // Bit 1: Intercept INIT
|
||||
|
||||
// // MTRRs (Memory Type Range Registers)
|
||||
#define MSR_MTRR4kBase 0x00000268 // MSR_MTRRfix4K_C0000 (primer registro 4k)
|
||||
#define MSR_MTRRVarBase 0x00000200 // MTRR variable base (MSR_MTRRphysBase0)
|
||||
|
||||
#define VRAM_BASE (0x470000000 - info.vram_size)
|
||||
|
||||
#define FB_BASE 0xf400000000
|
||||
|
||||
#define ACPI_RSDP_ADDRESS 0x7fd8e014
|
||||
|
||||
#define AMDGPU_MMIO_BASE 0xe0600000
|
||||
|
||||
#define RCC_CONFIG_MEMSIZE 0x378c
|
||||
|
||||
#define GCMC_VM_FB_OFFSET 0xa5ac
|
||||
#define GCMC_VM_LOCAL_HBM_ADDRESS_START 0xa5d4
|
||||
#define GCMC_VM_LOCAL_HBM_ADDRESS_END 0xa5d8
|
||||
#define GCMC_VM_FB_LOCATION_BASE 0xa600
|
||||
#define GCMC_VM_FB_LOCATION_TOP 0xa604
|
||||
|
||||
#define MMMC_VM_FB_OFFSET 0x6a15c
|
||||
#define MMMC_VM_LOCAL_HBM_ADDRESS_START 0x6a184
|
||||
#define MMMC_VM_LOCAL_HBM_ADDRESS_END 0x6a188
|
||||
#define MMMC_VM_FB_LOCATION_BASE 0x6a1b0
|
||||
#define MMMC_VM_FB_LOCATION_TOP 0x6a1b4
|
||||
|
||||
#define MMHUBBUB_WHITELIST_BASE_ADDR_0 0x24850
|
||||
#define MMHUBBUB_WHITELIST_TOP_ADDR_0 0x24854
|
||||
#define DCHUBBUB_WHITELIST_BASE_ADDR_0 0x24878
|
||||
#define DCHUBBUB_WHITELIST_TOP_ADDR_0 0x2487c
|
||||
|
||||
#define MAXCPU 16
|
||||
|
||||
void entry(void);
|
||||
void boot_linux(void);
|
||||
@@ -0,0 +1,18 @@
|
||||
/* linker.ld */
|
||||
ENTRY(main)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x1000; /* 0x1000 to avoid warnings from linker */
|
||||
/* Place our custom header first */
|
||||
.shell_code :
|
||||
{
|
||||
*(.entry_point)
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.data*)
|
||||
*(.rodata*)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2026 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_H__
|
||||
#define __LINUX_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define X86_SUBARCH_PS5 5
|
||||
|
||||
enum e820_type {
|
||||
E820_TYPE_RAM = 1,
|
||||
E820_TYPE_RESERVED = 2,
|
||||
E820_TYPE_ACPI = 3,
|
||||
E820_TYPE_NVS = 4,
|
||||
E820_TYPE_UNUSABLE = 5,
|
||||
E820_TYPE_PMEM = 7,
|
||||
E820_TYPE_PRAM = 12,
|
||||
E820_TYPE_SOFT_RESERVED = 0xefffffff,
|
||||
};
|
||||
|
||||
struct boot_e820_entry {
|
||||
uint64_t addr;
|
||||
uint64_t size;
|
||||
uint32_t type;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct setup_header {
|
||||
uint8_t setup_sects;
|
||||
uint16_t root_flags;
|
||||
uint32_t syssize;
|
||||
uint16_t ram_size;
|
||||
uint16_t vid_mode;
|
||||
uint16_t root_dev;
|
||||
uint16_t boot_flag;
|
||||
uint16_t jump;
|
||||
uint32_t header;
|
||||
uint16_t version;
|
||||
uint32_t realmode_swtch;
|
||||
uint16_t start_sys_seg;
|
||||
uint16_t kernel_version;
|
||||
uint8_t type_of_loader;
|
||||
uint8_t loadflags;
|
||||
uint16_t setup_move_size;
|
||||
uint32_t code32_start;
|
||||
uint32_t ramdisk_image;
|
||||
uint32_t ramdisk_size;
|
||||
uint32_t bootsect_kludge;
|
||||
uint16_t heap_end_ptr;
|
||||
uint8_t ext_loader_ver;
|
||||
uint8_t ext_loader_type;
|
||||
uint32_t cmd_line_ptr;
|
||||
uint32_t initrd_addr_max;
|
||||
uint32_t kernel_alignment;
|
||||
uint8_t relocatable_kernel;
|
||||
uint8_t min_alignment;
|
||||
uint16_t xloadflags;
|
||||
uint32_t cmdline_size;
|
||||
uint32_t hardware_subarch;
|
||||
uint64_t hardware_subarch_data;
|
||||
uint32_t payload_offset;
|
||||
uint32_t payload_length;
|
||||
uint64_t setup_data;
|
||||
uint64_t pref_address;
|
||||
uint32_t init_size;
|
||||
uint32_t handover_offset;
|
||||
uint32_t kernel_info_offset;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define E820_MAX_ENTRIES_ZEROPAGE 128
|
||||
|
||||
struct boot_params {
|
||||
uint8_t screen_info[0x40]; // 0x000
|
||||
uint8_t apm_bios_info[0x14]; // 0x040
|
||||
uint8_t _pad2[4]; // 0x054
|
||||
uint64_t tboot_addr; // 0x058
|
||||
uint8_t ist_info[0x10]; // 0x060
|
||||
uint64_t acpi_rsdp_addr; // 0x070
|
||||
uint8_t _pad3[8]; // 0x078
|
||||
uint8_t hd0_info[16]; // 0x080
|
||||
uint8_t hd1_info[16]; // 0x090
|
||||
uint8_t sys_desc_table[0x10]; // 0x0a0
|
||||
uint8_t olpc_ofw_header[0x10]; // 0x0b0
|
||||
uint32_t ext_ramdisk_image; // 0x0c0
|
||||
uint32_t ext_ramdisk_size; // 0x0c4
|
||||
uint32_t ext_cmd_line_ptr; // 0x0c8
|
||||
uint8_t _pad4[112]; // 0x0cc
|
||||
uint32_t cc_blob_address; // 0x13c
|
||||
uint8_t edid_info[0x80]; // 0x140
|
||||
uint8_t efi_info[0x20]; // 0x1c0
|
||||
uint32_t alt_mem_k; // 0x1e0
|
||||
uint32_t scratch; // 0x1e4
|
||||
uint8_t e820_entries; // 0x1e8
|
||||
uint8_t eddbuf_entries; // 0x1e9
|
||||
uint8_t edd_mbr_sig_buf_entries; // 0x1ea
|
||||
uint8_t kbd_status; // 0x1eb
|
||||
uint8_t secure_boot; // 0x1ec
|
||||
uint8_t _pad5[2]; // 0x1ed
|
||||
uint8_t sentinel; // 0x1ef
|
||||
uint8_t _pad6[1]; // 0x1f0
|
||||
struct setup_header hdr; // 0x1f1
|
||||
uint8_t _pad7[0x290 - 0x1f1 - sizeof(struct setup_header)];
|
||||
uint32_t edd_mbr_sig_buffer[16]; // 0x290
|
||||
struct boot_e820_entry e820_table[E820_MAX_ENTRIES_ZEROPAGE]; // 0x2d0
|
||||
uint8_t _pad8[48]; // 0xcd0
|
||||
uint8_t eddbuf[0x1ec]; // 0xd00
|
||||
uint8_t _pad9[276]; // 0xeec
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
#include "main.h"
|
||||
#include "../include/config.h"
|
||||
#include "boot_linux.h"
|
||||
#include "utils.h"
|
||||
#include <cpuid.h>
|
||||
#include <machine/atomic.h>
|
||||
#include <machine/cpufunc.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__attribute__((section(".entry_point"), naked)) uint32_t main(void) {
|
||||
|
||||
// We enter this function after CR3 was updated to 1:1 mapping
|
||||
// We need to point RSP/RBP to a good known valid address
|
||||
uint32_t ebax, ebx, ecx, edx;
|
||||
uint32_t cpu_id;
|
||||
|
||||
__asm__ volatile("cpuid"
|
||||
: "=a"(ebax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(1));
|
||||
|
||||
cpu_id = (ebx >> 24) & 0xFF;
|
||||
|
||||
// We point to a location after the main linux boot code
|
||||
// Each CPU should have a different location
|
||||
uintptr_t new_rsp =
|
||||
(uintptr_t)hv_base_rsp + ((uint64_t)(cpu_id)*hv_stack_size);
|
||||
|
||||
// WARNING: This invalidates current local variables
|
||||
__asm__ volatile("movq %0, %%rsp \n\t"
|
||||
"movq %%rsp, %%rbp \n\t"
|
||||
:
|
||||
: "r"(new_rsp)
|
||||
: "rsp", "rbp", "memory");
|
||||
|
||||
entry();
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "shellcode_hypervisor_args.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user