启动脚本长这样。
#!/bin/sh
./qemu-system-x86_64 -initrd ./initramfs-busybox-x64.cpio.gz -nographic -kernel ./vmlinuz-5.0.5-generic -append "priority=low console=ttyS0" -monitor /dev/null --device FastCP

绿肯定是全绿
设备是FastCP

这是里面设备结构体的全貌
里面还有一个叫CP_state的结构体
三个参数
FastCP_realize函数中设置了一个定时器
定时器时间到了会调用fastcp_cp_timer函数
然后创建了一个mmio

fastcp_mmio_read
功能0x00 返回opaque->handling
功能0x08 返回opaque->cp_state.CP_list_src
功能0x10 返回opaque->cp_state.CP_list_cnt
功能0x18 返回opaque->cp_state.cmd
fastcp_mmio_write
功能0x08 给cp_list_src赋值
功能0x10 handing不是1的情况下给cp_list_cnt赋值
功能0x18 handing不是1的情况下给cp_list_cmd赋值然后调用timer
然后我们瞅瞅fastcp_cp_timer函数
void __fastcall fastcp_cp_timer(FastCPState *opaque)
{
uint64_t v1; // rax
uint64_t v2; // rdx
__int64 v3; // rbp
uint64_t v4; // r12
uint64_t v5; // rax
uint64_t v6; // rax
bool v7; // zf
uint64_t v8; // rbp
__int64 v9; // rdx
FastCP_CP_INFO cp_info; // [rsp+0h] [rbp-68h] BYREF
char buf[8]; // [rsp+20h] [rbp-48h] BYREF
unsigned __int64 v12; // [rsp+28h] [rbp-40h]
unsigned __int64 v13; // [rsp+38h] [rbp-30h]
v13 = __readfsqword(0x28u);
v1 = opaque->cp_state.cmd;
cp_info.CP_src = 0LL;
cp_info.CP_cnt = 0LL;
cp_info.CP_dst = 0LL;
switch ( v1 ) // cp_state.cmd来做选择
{
case 2uLL: // 选择2
v7 = opaque->cp_state.CP_list_cnt == 1; // v7是cp_list_cnt是不是1
opaque->handling = 1; // handing置1
// 也就是不再给计时器机会
if ( v7 ) // 要求v7是1也就是cp_list_cnt不是1
{
// cpu_physical_memory_rw(a1, a2, a3, 1);是将a2复制到a1,而cpu_physical_memory_rw(a1, a2, a3, 0);则将a1复制到a2
// 但是要注意的是,cpu_physical_memory_rw的第一个参数为硬件地址,即物理地址,所以我们需要将qemu里面的虚拟地址,转化为物理地址。
cpu_physical_memory_rw(opaque->cp_state.CP_list_src, &cp_info, 0x18uLL, 0);// 所以就list_src里面的复制0x18个字节到cp_info结构体
if ( cp_info.CP_cnt <= 0x1000 ) // cp_cnt必须小于0x1000
// 然后就可以把cp_info.cp_src中的复制到cp_buffer
cpu_physical_memory_rw(cp_info.CP_src, opaque->CP_buffer, cp_info.CP_cnt, 0);
v6 = opaque->cp_state.cmd & 0xFFFFFFFFFFFFFFFCLL;
opaque->cp_state.cmd = v6;
goto LABEL_11; // 然后拜拜
}
break;
case 4uLL:
v7 = opaque->cp_state.CP_list_cnt == 1;
opaque->handling = 1;
if ( v7 ) // cp_list_cnt还得不是1
{
// 还是list_src写进去cp_info结构体
// cp_buffer又能写cnt个到cp_dst
cpu_physical_memory_rw(opaque->cp_state.CP_list_src, &cp_info, 0x18uLL, 0);
cpu_physical_memory_rw(cp_info.CP_dst, opaque->CP_buffer, cp_info.CP_cnt, 1);// 这里没有对这个cnt有检查
v6 = opaque->cp_state.cmd & 0xFFFFFFFFFFFFFFF8LL;
opaque->cp_state.cmd = v6; // 然后又拜拜
LABEL_11:
if ( (v6 & 8) != 0 ) // cmd要求是8
{
opaque->irq_status |= 0x100u;
if ( msi_enabled(&opaque->pdev) )
msi_notify(&opaque->pdev, 0);
else
pci_set_irq(&opaque->pdev, 1);
}
goto LABEL_16; // 但是走了这个地方之后又handing等于0了
// 就又能启动timer了
}
break<

最低0.47元/天 解锁文章
869





