Compare commits

...
1 Commits
Author SHA1 Message Date
Martijn de Vos 8bac900779 WIP 2021-10-24 10:39:49 +02:00
10 changed files with 737 additions and 0 deletions

No files matched your search

@@ -7,3 +7,4 @@
CONFIG_ARM_VIRT=y
CONFIG_SBSA_REF=y
CONFIG_IPHONE_6SPLUS=y
+1
View File
@@ -42,3 +42,4 @@ CONFIG_FSL_IMX6UL=y
CONFIG_SEMIHOSTING=y
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
CONFIG_ALLWINNER_H3=y
CONFIG_IPHONE_6SPLUS=y
+4
View File
@@ -548,3 +548,7 @@ config ARMSSE
select UNIMP
select SSE_COUNTER
select SSE_TIMER
config IPHONE_6SPLUS
bool
select IPHONE_6SPLUS
+296
View File
@@ -0,0 +1,296 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "hw/arm/boot.h"
#include "exec/address-spaces.h"
#include "hw/misc/unimp.h"
#include "sysemu/sysemu.h"
#include "sysemu/reset.h"
#include "qemu/error-report.h"
#include "hw/platform-bus.h"
#include "hw/arm/iphone6splus.h"
#define N66_PHYS_BASE (0x40000000)
#define N66_CPREG_FUNCS(name) \
static uint64_t n66_cpreg_read_##name(CPUARMState *env, \
const ARMCPRegInfo *ri) \
{ \
N66MachineState *nms = (N66MachineState *)ri->opaque; \
return nms->N66_CPREG_VAR_NAME(name); \
} \
static void n66_cpreg_write_##name(CPUARMState *env, const ARMCPRegInfo *ri, \
uint64_t value) \
{ \
N66MachineState *nms = (N66MachineState *)ri->opaque; \
nms->N66_CPREG_VAR_NAME(name) = value; \
}
#define N66_CPREG_DEF(p_name, p_op0, p_op1, p_crn, p_crm, p_op2, p_access) \
{ .cp = CP_REG_ARM64_SYSREG_CP, \
.name = #p_name, .opc0 = p_op0, .crn = p_crn, .crm = p_crm, \
.opc1 = p_op1, .opc2 = p_op2, .access = p_access, .type = ARM_CP_IO, \
.state = ARM_CP_STATE_AA64, .readfn = n66_cpreg_read_##p_name, \
.writefn = n66_cpreg_write_##p_name }
N66_CPREG_FUNCS(ARM64_REG_HID11)
N66_CPREG_FUNCS(ARM64_REG_HID3)
N66_CPREG_FUNCS(ARM64_REG_HID5)
N66_CPREG_FUNCS(ARM64_REG_HID4)
N66_CPREG_FUNCS(ARM64_REG_HID8)
N66_CPREG_FUNCS(ARM64_REG_HID7)
N66_CPREG_FUNCS(ARM64_REG_LSU_ERR_STS)
N66_CPREG_FUNCS(PMC0)
N66_CPREG_FUNCS(PMC1)
N66_CPREG_FUNCS(PMCR1)
N66_CPREG_FUNCS(PMSR)
// This is the same as the array for kvm, but without
// the L2ACTLR_EL1, which is already defined in TCG.
// Duplicating this list isn't a perfect solution,
// but it's quick and reliable.
static const ARMCPRegInfo n66_cp_reginfo_tcg[] = {
// Apple-specific registers
N66_CPREG_DEF(ARM64_REG_HID11, 3, 0, 15, 13, 0, PL1_RW),
N66_CPREG_DEF(ARM64_REG_HID3, 3, 0, 15, 3, 0, PL1_RW),
N66_CPREG_DEF(ARM64_REG_HID5, 3, 0, 15, 5, 0, PL1_RW),
N66_CPREG_DEF(ARM64_REG_HID4, 3, 0, 15, 4, 0, PL1_RW),
N66_CPREG_DEF(ARM64_REG_HID8, 3, 0, 15, 8, 0, PL1_RW),
N66_CPREG_DEF(ARM64_REG_HID7, 3, 0, 15, 7, 0, PL1_RW),
N66_CPREG_DEF(ARM64_REG_LSU_ERR_STS, 3, 3, 15, 0, 0, PL1_RW),
N66_CPREG_DEF(PMC0, 3, 2, 15, 0, 0, PL1_RW),
N66_CPREG_DEF(PMC1, 3, 2, 15, 1, 0, PL1_RW),
N66_CPREG_DEF(PMCR1, 3, 1, 15, 1, 0, PL1_RW),
N66_CPREG_DEF(PMSR, 3, 1, 15, 13, 0, PL1_RW),
REGINFO_SENTINEL,
};
static void n66_add_cpregs(N66MachineState *nms)
{
ARMCPU *cpu = nms->cpu;
nms->N66_CPREG_VAR_NAME(ARM64_REG_HID11) = 0;
nms->N66_CPREG_VAR_NAME(ARM64_REG_HID3) = 0;
nms->N66_CPREG_VAR_NAME(ARM64_REG_HID5) = 0;
nms->N66_CPREG_VAR_NAME(ARM64_REG_HID8) = 0;
nms->N66_CPREG_VAR_NAME(ARM64_REG_HID7) = 0;
nms->N66_CPREG_VAR_NAME(ARM64_REG_LSU_ERR_STS) = 0;
nms->N66_CPREG_VAR_NAME(PMC0) = 0;
nms->N66_CPREG_VAR_NAME(PMC1) = 0;
nms->N66_CPREG_VAR_NAME(PMCR1) = 0;
nms->N66_CPREG_VAR_NAME(PMSR) = 0;
nms->N66_CPREG_VAR_NAME(L2ACTLR_EL1) = 0;
define_arm_cp_regs_with_opaque(cpu, n66_cp_reginfo_tcg, nms);
}
static void n66_ns_memory_setup(MachineState *machine, MemoryRegion *sysmem,
AddressSpace *nsas)
{
uint64_t used_ram_for_blobs = 0;
hwaddr kernel_low;
hwaddr kernel_high;
hwaddr virt_base;
hwaddr dtb_va;
uint64_t dtb_size;
hwaddr kbootargs_pa;
hwaddr top_of_kernel_data_pa;
hwaddr mem_size;
hwaddr remaining_mem_size;
hwaddr allocated_ram_pa;
hwaddr phys_ptr;
hwaddr phys_pc;
hwaddr ramfb_pa = 0;
video_boot_args v_bootargs = {0};
N66MachineState *nms = N66_MACHINE(machine);
//setup the memory layout:
//At the beginning of the non-secure ram we have the raw kernel file.
//After that we have the static trust cache.
//After that we have all the kernel sections.
//After that we have ramdosk
//After that we have the device tree
//After that we have the kernel boot args
//After that we have the rest of the RAM
macho_file_highest_lowest_base(nms->kernel_filename, N66_PHYS_BASE,
&virt_base, &kernel_low, &kernel_high);
g_virt_base = virt_base;
g_phys_base = N66_PHYS_BASE;
phys_ptr = N66_PHYS_BASE;
//now account for the loaded kernel
arm_load_macho(nms->kernel_filename, nsas, sysmem, "kernel.n66",
N66_PHYS_BASE, virt_base, kernel_low,
kernel_high, &phys_pc);
nms->kpc_pa = phys_pc;
used_ram_for_blobs += (align_64k_high(kernel_high) - kernel_low);
phys_ptr = align_64k_high(vtop_static(kernel_high));
// TODO load other stuff
//now account for kernel boot args
used_ram_for_blobs += align_64k_high(sizeof(struct xnu_arm64_boot_args));
kbootargs_pa = phys_ptr;
nms->kbootargs_pa = kbootargs_pa;
phys_ptr += align_64k_high(sizeof(struct xnu_arm64_boot_args));
nms->extra_data_pa = phys_ptr;
allocated_ram_pa = phys_ptr;
// TODO ramfb
//phys_ptr += align_64k_high(sizeof(AllocatedData));
top_of_kernel_data_pa = phys_ptr;
remaining_mem_size = machine->ram_size - used_ram_for_blobs;
mem_size = allocated_ram_pa - N66_PHYS_BASE + remaining_mem_size;
macho_setup_bootargs("k_bootargs.n66", nsas, sysmem, kbootargs_pa,
virt_base, N66_PHYS_BASE, mem_size,
top_of_kernel_data_pa, dtb_va, dtb_size,
v_bootargs, nms->kern_args);
allocate_ram(sysmem, "n66.ram", allocated_ram_pa, remaining_mem_size);
}
static void n66_memory_setup(MachineState *machine,
MemoryRegion *sysmem,
MemoryRegion *secure_sysmem,
AddressSpace *nsas)
{
n66_ns_memory_setup(machine, sysmem, nsas);
}
static void n66_cpu_setup(MachineState *machine, MemoryRegion **sysmem,
MemoryRegion **secure_sysmem, ARMCPU **cpu,
AddressSpace **nsas)
{
Object *cpuobj = object_new(machine->cpu_type);
*cpu = ARM_CPU(cpuobj);
CPUState *cs = CPU(*cpu);
*sysmem = get_system_memory();
object_property_set_link(cpuobj, "memory", OBJECT(*sysmem), &error_abort);
//set secure monitor to false
object_property_set_bool(cpuobj, "has_el3", false, NULL);
object_property_set_bool(cpuobj, "has_el2", false, NULL);
object_property_set_bool(cpuobj, "realized", true, &error_fatal);
*nsas = cpu_get_address_space(cs, ARMASIdx_NS);
object_unref(cpuobj);
//currently support only a single CPU and thus
//use no interrupt controller and wire IRQs from devices directly to the CPU
}
static void n66_cpu_reset(void *opaque)
{
N66MachineState *nms = N66_MACHINE((MachineState *)opaque);
ARMCPU *cpu = nms->cpu;
CPUState *cs = CPU(cpu);
CPUARMState *env = &cpu->env;
cpu_reset(cs);
env->xregs[0] = nms->kbootargs_pa;
env->pc = nms->kpc_pa;
}
static void n66_machine_init(MachineState *machine)
{
N66MachineState *nms = N66_MACHINE(machine);
MemoryRegion *sysmem;
MemoryRegion *secure_sysmem;
AddressSpace *nsas;
ARMCPU *cpu;
CPUState *cs;
DeviceState *cpudev;
n66_cpu_setup(machine, &sysmem, &secure_sysmem, &cpu, &nsas);
nms->cpu = cpu;
n66_memory_setup(machine, sysmem, secure_sysmem, nsas);
// TODO finish
n66_add_cpregs(nms);
// TODO finish
qemu_register_reset(n66_cpu_reset, nms);
}
static void n66_set_kernel_filename(Object *obj, const char *value,
Error **errp)
{
N66MachineState *nms = N66_MACHINE(obj);
g_strlcpy(nms->kernel_filename, value, sizeof(nms->kernel_filename));
}
static char *n66_get_kernel_filename(Object *obj, Error **errp)
{
N66MachineState *nms = N66_MACHINE(obj);
return g_strdup(nms->kernel_filename);
}
static void n66_set_kern_args(Object *obj, const char *value,
Error **errp)
{
N66MachineState *nms = N66_MACHINE(obj);
g_strlcpy(nms->kern_args, value, sizeof(nms->kern_args));
}
static char *n66_get_kern_args(Object *obj, Error **errp)
{
N66MachineState *nms = N66_MACHINE(obj);
return g_strdup(nms->kern_args);
}
static void n66_instance_init(Object *obj)
{
object_property_add_str(obj, "kernel-filename", n66_get_kernel_filename, n66_set_kernel_filename);
object_property_set_description(obj, "kernel-filename", "Set the kernel filename");
object_property_add_str(obj, "kern-cmd-args", n66_get_kern_args, n66_set_kern_args);
object_property_set_description(obj, "kern-cmd-args", "Set the XNU kernel cmd args");
// TODO
}
static void n66_machine_class_init(ObjectClass *klass, void *data)
{
MachineClass *mc = MACHINE_CLASS(klass);
mc->desc = "iPhone 6s plus (n66 - s8000)";
mc->init = n66_machine_init;
mc->max_cpus = 1;
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->no_parallel = 1;
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a57");
mc->minimum_page_bits = 12;
}
static const TypeInfo n66_machine_info = {
.name = TYPE_N66_MACHINE,
.parent = TYPE_MACHINE,
.instance_size = sizeof(N66MachineState),
.class_size = sizeof(N66MachineClass),
.class_init = n66_machine_class_init,
.instance_init = n66_instance_init,
};
static void n66_machine_types(void)
{
type_register_static(&n66_machine_info);
}
type_init(n66_machine_types)
+1
View File
@@ -58,5 +58,6 @@ arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.
arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c', 'smmuv3.c'))
arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
arm_ss.add(when: 'CONFIG_IPHONE_6SPLUS', if_true: files('iphone6splus.c', 'xnu.c', 'xnu_mem.c'))
hw_arch += {'arm': arm_ss}
+170
View File
@@ -0,0 +1,170 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "hw/arm/boot.h"
#include "sysemu/sysemu.h"
#include "qemu/error-report.h"
#include "hw/arm/xnu.h"
#include "hw/loader.h"
static void allocate_and_copy(MemoryRegion *mem, AddressSpace *as,
const char *name, hwaddr pa, hwaddr size,
void *buf)
{
if (mem) {
allocate_ram(mem, name, pa, align_64k_high(size));
}
address_space_rw(as, pa, MEMTXATTRS_UNSPECIFIED, (uint8_t *)buf, size, 1);
}
void macho_setup_bootargs(const char *name, AddressSpace *as,
MemoryRegion *mem, hwaddr bootargs_pa,
hwaddr virt_base, hwaddr phys_base, hwaddr mem_size,
hwaddr top_of_kernel_data_pa, hwaddr dtb_va,
hwaddr dtb_size, video_boot_args v_bootargs,
char *kern_args)
{
struct xnu_arm64_boot_args boot_args;
memset(&boot_args, 0, sizeof(boot_args));
boot_args.Revision = xnu_arm64_kBootArgsRevision2;
boot_args.Version = xnu_arm64_kBootArgsVersion2;
boot_args.virtBase = virt_base;
boot_args.physBase = phys_base;
boot_args.memSize = mem_size;
boot_args.Video.v_baseAddr = v_bootargs.v_baseAddr;
boot_args.Video.v_depth = v_bootargs.v_depth;
boot_args.Video.v_display = v_bootargs.v_display;
boot_args.Video.v_height = v_bootargs.v_height;
boot_args.Video.v_rowBytes = v_bootargs.v_rowBytes;
boot_args.Video.v_width = v_bootargs.v_width;
boot_args.topOfKernelData = top_of_kernel_data_pa;
boot_args.deviceTreeP = dtb_va;
boot_args.deviceTreeLength = dtb_size;
boot_args.memSizeActual = 0;
if (kern_args) {
g_strlcpy(boot_args.CommandLine, kern_args,
sizeof(boot_args.CommandLine));
}
allocate_and_copy(mem, as, name, bootargs_pa, sizeof(boot_args),
&boot_args);
}
static void macho_highest_lowest(struct mach_header_64* mh, uint64_t *lowaddr,
uint64_t *highaddr)
{
struct load_command* cmd = (struct load_command*)((uint8_t*)mh +
sizeof(struct mach_header_64));
// iterate all the segments once to find highest and lowest addresses
uint64_t low_addr_temp = ~0;
uint64_t high_addr_temp = 0;
for (unsigned int index = 0; index < mh->ncmds; index++) {
switch (cmd->cmd) {
case LC_SEGMENT_64: {
struct segment_command_64 *segCmd =
(struct segment_command_64 *)cmd;
if (segCmd->vmaddr < low_addr_temp) {
low_addr_temp = segCmd->vmaddr;
}
if (segCmd->vmaddr + segCmd->vmsize > high_addr_temp) {
high_addr_temp = segCmd->vmaddr + segCmd->vmsize;
}
break;
}
}
cmd = (struct load_command*)((char*)cmd + cmd->cmdsize);
}
*lowaddr = low_addr_temp;
*highaddr = high_addr_temp;
}
static void macho_file_highest_lowest(const char *filename, hwaddr *lowest,
hwaddr *highest)
{
gsize len;
uint8_t *data = NULL;
if (!g_file_get_contents(filename, (char **)&data, &len, NULL)) {
abort();
}
struct mach_header_64* mh = (struct mach_header_64*)data;
macho_highest_lowest(mh, lowest, highest);
g_free(data);
}
void macho_file_highest_lowest_base(const char *filename, hwaddr phys_base,
hwaddr *virt_base, hwaddr *lowest,
hwaddr *highest)
{
uint8_t high_Low_dif_bit_index;
uint8_t phys_base_non_zero_bit_index;
hwaddr bit_mask_for_index;
macho_file_highest_lowest(filename, lowest, highest);
high_Low_dif_bit_index =
get_highest_different_bit_index(align_64k_high(*highest),
align_64k_low(*lowest));
if (phys_base) {
phys_base_non_zero_bit_index =
get_lowest_non_zero_bit_index(phys_base);
//make sure we have enough zero bits to have all the diffrent kernel
//image addresses have the same non static bits in physical and in
//virtual memory.
if (high_Low_dif_bit_index > phys_base_non_zero_bit_index) {
abort();
}
bit_mask_for_index =
get_low_bits_mask_for_bit_index(phys_base_non_zero_bit_index);
*virt_base = align_64k_low(*lowest) & (~bit_mask_for_index);
}
}
void arm_load_macho(char *filename, AddressSpace *as, MemoryRegion *mem,
const char *name, hwaddr phys_base, hwaddr virt_base,
hwaddr low_virt_addr, hwaddr high_virt_addr, hwaddr *pc)
{
uint8_t *data = NULL;
gsize len;
uint8_t* rom_buf = NULL;
if (!g_file_get_contents(filename, (char **)&data, &len, NULL)) {
abort();
}
struct mach_header_64* mh = (struct mach_header_64*)data;
struct load_command* cmd = (struct load_command*)(data +
sizeof(struct mach_header_64));
uint64_t rom_buf_size = align_64k_high(high_virt_addr) - low_virt_addr;
rom_buf = g_malloc0(rom_buf_size);
for (unsigned int index = 0; index < mh->ncmds; index++) {
switch (cmd->cmd) {
case LC_SEGMENT_64: {
struct segment_command_64 *segCmd =
(struct segment_command_64 *)cmd;
memcpy(rom_buf + (segCmd->vmaddr - low_virt_addr),
data + segCmd->fileoff, segCmd->filesize);
break;
}
case LC_UNIXTHREAD: {
// grab just the entry point PC
uint64_t* ptrPc = (uint64_t*)((char*)cmd + 0x110);
// 0x110 for arm64 only.
*pc = vtop_bases(*ptrPc, phys_base, virt_base);
break;
}
}
cmd = (struct load_command*)((char*)cmd + cmd->cmdsize);
}
hwaddr low_phys_addr = vtop_bases(low_virt_addr, phys_base, virt_base);
allocate_and_copy(mem, as, name, low_phys_addr, rom_buf_size, rom_buf);
if (data) {
g_free(data);
}
if (rom_buf) {
g_free(rom_buf);
}
}
+100
View File
@@ -0,0 +1,100 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "hw/arm/boot.h"
#include "exec/address-spaces.h"
#include "hw/misc/unimp.h"
#include "sysemu/sysemu.h"
#include "qemu/error-report.h"
#include "hw/platform-bus.h"
#include "exec/memory.h"
#include "qemu-common.h"
#include "exec/hwaddr.h"
#include "hw/boards.h"
#include "hw/arm/boot.h"
#include "cpu.h"
#include "hw/arm/xnu_mem.h"
hwaddr g_virt_base = 0;
hwaddr g_phys_base = 0;
hwaddr vtop_bases(hwaddr va, hwaddr phys_base, hwaddr virt_base)
{
if ((0 == virt_base) || (0 == phys_base)) {
abort();
}
return va - virt_base + phys_base;
}
hwaddr ptov_bases(hwaddr pa, hwaddr phys_base, hwaddr virt_base)
{
if ((0 == virt_base) || (0 == phys_base)) {
abort();
}
return pa - phys_base + virt_base;
}
hwaddr vtop_static(hwaddr va)
{
return vtop_bases(va, g_phys_base, g_virt_base);
}
hwaddr ptov_static(hwaddr pa)
{
return ptov_bases(pa, g_phys_base, g_virt_base);
}
hwaddr vtop_mmu(hwaddr va, CPUState *cs)
{
hwaddr phys_addr;
MemTxAttrs attrs = {};
phys_addr = arm_cpu_get_phys_page_attrs_debug(cs, va, &attrs);
if (-1 == phys_addr) {
abort();
}
return phys_addr;
}
uint8_t get_highest_different_bit_index(hwaddr addr1, hwaddr addr2)
{
if ((addr1 == addr2) || (0 == addr1) || (0 == addr2)) {
abort();
}
return (64 - __builtin_clzll(addr1 ^ addr2));
}
hwaddr align_64k_low(hwaddr addr)
{
return addr & ~0xffffull;
}
hwaddr align_64k_high(hwaddr addr)
{
return (addr + 0xffffull) & ~0xffffull;
}
uint8_t get_lowest_non_zero_bit_index(hwaddr addr)
{
if (0 == addr) {
abort();
}
return __builtin_ctzll(addr);
}
hwaddr get_low_bits_mask_for_bit_index(uint8_t bit_index)
{
if (bit_index >= 64) {
abort();
}
return (1 << bit_index) - 1;
}
void allocate_ram(MemoryRegion *top, const char *name, hwaddr addr,
hwaddr size)
{
MemoryRegion *sec = g_new(MemoryRegion, 1);
memory_region_init_ram(sec, NULL, name, size, &error_fatal);
memory_region_add_subregion(top, addr, sec);
}
+49
View File
@@ -0,0 +1,49 @@
#ifndef HW_ARM_N66_H
#define HW_ARM_N66_H
#include "qemu-common.h"
#include "exec/hwaddr.h"
#include "hw/boards.h"
#include "hw/arm/boot.h"
#include "hw/arm/xnu.h"
#include "exec/memory.h"
#include "cpu.h"
#include "sysemu/kvm.h"
#define TYPE_N66 "iPhone6splus-n66-s8000"
#define TYPE_N66_MACHINE MACHINE_TYPE_NAME(TYPE_N66)
#define N66_MACHINE(obj) \
OBJECT_CHECK(N66MachineState, (obj), TYPE_N66_MACHINE)
#define N66_CPREG_VAR_NAME(name) cpreg_##name
#define N66_CPREG_VAR_DEF(name) uint64_t N66_CPREG_VAR_NAME(name)
typedef struct {
MachineClass parent;
} N66MachineClass;
typedef struct {
MachineState parent;
hwaddr extra_data_pa;
hwaddr kpc_pa;
hwaddr kbootargs_pa;
ARMCPU *cpu;
char kernel_filename[1024];
char kern_args[1024];
N66_CPREG_VAR_DEF(ARM64_REG_HID11);
N66_CPREG_VAR_DEF(ARM64_REG_HID3);
N66_CPREG_VAR_DEF(ARM64_REG_HID5);
N66_CPREG_VAR_DEF(ARM64_REG_HID4);
N66_CPREG_VAR_DEF(ARM64_REG_HID8);
N66_CPREG_VAR_DEF(ARM64_REG_HID7);
N66_CPREG_VAR_DEF(ARM64_REG_LSU_ERR_STS);
N66_CPREG_VAR_DEF(PMC0);
N66_CPREG_VAR_DEF(PMC1);
N66_CPREG_VAR_DEF(PMCR1);
N66_CPREG_VAR_DEF(PMSR);
N66_CPREG_VAR_DEF(L2ACTLR_EL1);
} N66MachineState;
#endif
+88
View File
@@ -0,0 +1,88 @@
#ifndef HW_ARM_XNU_H
#define HW_ARM_XNU_H
#include "qemu-common.h"
#include "hw/arm/boot.h"
#include "hw/arm/xnu_mem.h"
// pexpert/pexpert/arm64/boot.h
#define xnu_arm64_kBootArgsRevision2 2 /* added boot_args.bootFlags */
#define xnu_arm64_kBootArgsVersion2 2
#define xnu_arm64_BOOT_LINE_LENGTH 256
#define LC_SEGMENT_64 0x19
#define LC_UNIXTHREAD 0x5
struct segment_command_64
{
uint32_t cmd;
uint32_t cmdsize;
char segname[16];
uint64_t vmaddr;
uint64_t vmsize;
uint64_t fileoff;
uint64_t filesize;
uint32_t /*vm_prot_t*/ maxprot;
uint32_t /*vm_prot_t*/ initprot;
uint32_t nsects;
uint32_t flags;
};
struct mach_header_64 {
uint32_t magic; /* mach magic number identifier */
uint32_t /*cpu_type_t*/ cputype; /* cpu specifier */
uint32_t /*cpu_subtype_t*/ cpusubtype; /* machine specifier */
uint32_t filetype; /* type of file */
uint32_t ncmds; /* number of load commands */
uint32_t sizeofcmds; /* the size of all the load commands */
uint32_t flags; /* flags */
uint32_t reserved; /* reserved */
};
struct load_command {
uint32_t cmd; /* type of load command */
uint32_t cmdsize; /* total size of command in bytes */
};
typedef struct xnu_arm64_video_boot_args {
unsigned long v_baseAddr; /* Base address of video memory */
unsigned long v_display; /* Display Code (if Applicable */
unsigned long v_rowBytes; /* Number of bytes per pixel row */
unsigned long v_width; /* Width */
unsigned long v_height; /* Height */
unsigned long v_depth; /* Pixel Depth and other parameters */
} video_boot_args;
struct xnu_arm64_boot_args {
uint16_t Revision; /* Revision of boot_args structure */
uint16_t Version; /* Version of boot_args structure */
uint64_t virtBase; /* Virtual base of memory */
uint64_t physBase; /* Physical base of memory */
uint64_t memSize; /* Size of memory */
uint64_t topOfKernelData; /* Highest physical address used in kernel data area */
video_boot_args Video; /* Video Information */
uint32_t machineType; /* Machine Type */
uint64_t deviceTreeP; /* Base of flattened device tree */
uint32_t deviceTreeLength; /* Length of flattened tree */
char CommandLine[xnu_arm64_BOOT_LINE_LENGTH]; /* Passed in command line */
uint64_t bootFlags; /* Additional flags specified by the bootloader */
uint64_t memSizeActual; /* Actual size of memory */
};
void macho_file_highest_lowest_base(const char *filename, hwaddr phys_base,
hwaddr *virt_base, hwaddr *lowest,
hwaddr *highest);
void macho_setup_bootargs(const char *name, AddressSpace *as,
MemoryRegion *mem, hwaddr bootargs_pa,
hwaddr virt_base, hwaddr phys_base, hwaddr mem_size,
hwaddr top_of_kernel_data_pa, hwaddr dtb_va,
hwaddr dtb_size, video_boot_args v_bootargs,
char *kern_args);
void arm_load_macho(char *filename, AddressSpace *as, MemoryRegion *mem,
const char *name, hwaddr phys_base, hwaddr virt_base,
hwaddr low_virt_addr, hwaddr high_virt_addr, hwaddr *pc);
#endif
+27
View File
@@ -0,0 +1,27 @@
#ifndef HW_ARM_XNU_MEM_H
#define HW_ARM_XNU_MEM_H
#include "qemu-common.h"
#include "hw/arm/boot.h"
#include "target/arm/cpu.h"
extern hwaddr g_virt_base;
extern hwaddr g_phys_base;
hwaddr vtop_static(hwaddr va);
hwaddr ptov_static(hwaddr pa);
hwaddr vtop_mmu(hwaddr va, CPUState *cs);
hwaddr align_64k_low(hwaddr addr);
hwaddr align_64k_high(hwaddr addr);
hwaddr vtop_bases(hwaddr va, hwaddr phys_base, hwaddr virt_base);
hwaddr ptov_bases(hwaddr pa, hwaddr phys_base, hwaddr virt_base);
uint8_t get_highest_different_bit_index(hwaddr addr1, hwaddr addr2);
uint8_t get_lowest_non_zero_bit_index(hwaddr addr);
hwaddr get_low_bits_mask_for_bit_index(uint8_t bit_index);
void allocate_ram(MemoryRegion *top, const char *name, hwaddr addr,
hwaddr size);
#endif