艰难的安装
最近用铭瑄H610-itx攒了一台nas,想着兼容性高一些专门买了H610的双网卡版本,一张是螃蟹的8125BG,一张是intel的i219V,还以为esxi总不能一个网卡都认不出来吧,然而装好机启动esxi8.0的安装程序一看,又是熟悉的没有网卡的报错一闪而过:
临时找了一个USB网卡凑合了一下,这里需要注意即使插了esxi能识别的usb网卡也依旧会在安装时卡在如下界面:
实际上这时候esxi已经安装完成了,只需要拔掉U盘重启就可以了,只不过重启后仍然无法自动获取ip:
这里只要按F2,登录名输入root 密码空着 直接回车就可以登录(大概是上一遍安装时输入的密码没有写入成功吧)
然后直接在Network Restore Options 里选择 Restore Network Settings,重置网络设置,就可以分配到IP了,然后再在Troubleshooting Options中手动把ssh打开,以便后续操作
驱动的秘密
其实8125BG没有驱动我可以接受,但是i219v之前查VMware官网应该是有支持的,于是lspci看了一下,发现我这张i219v的PCI ID是8086:0DC8,网上搜不到很多相关资料;
0000:00:1f.6 Network controller Ethernet controller: Intel Corporation Ethernet Connection (17) I219-V
Class 0200: 8086:0dc8
0000:01:00.0 Network controller Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8125 2.5GbE Controller
Class 0200: 10ec:8125
中间有阵子尝试了一下PVE,发现PVE可以正常识别这两张网卡,所以决定直接去翻linux内核里的驱动代码看看这个0DC8
的device id到底是什么网卡:
没想到果然是主板太新了,居然用的是i219V (22)
而整个linux内核源码对E1000_DEV_ID_PCH_RPL_I219_V22
这个宏的引用也只有这一个地方,看到后面跟的函数和E1000_DEV_ID_PCH_RPL_I219_V17
的函数是一模一样的,说明这两张网卡的驱动实现应该没什么区别。而ESXI是支持I219V (17)的,所以如果能**魔改esxi的intel网卡驱动,把其中关于I219V (17)的ID替换成I219V (22)**的,那么理论上就可以让esxi支持I219V (22)
于是首先在esxi里找了一下intel网卡驱动的存放位置,在/usr/lib/vmware/vmkmod/
目录下的ne1000这个文件:
scp到本地用010 Editor打开,搜索i219v (17) 的device id:1A1D
(由于字节序问题要反过来搜索1D1A)
可以看到驱动中确实有I219V (17)的PCI ID信息,理论上只要把这里改成C8 0D
(I219V (22) 的ID)就可以让驱动误以为网卡是I219V (17),然后正常加载
然而当我想尝试修改这个文件的时候却发现这个文件夹内的文件根本没法编辑,即便是简单改一下文件名也会有如下报错:
于是我又将修改后的驱动文件改名为ne1001,然后上传到了这个文件夹,想着如果ESXI内核会遍历这个文件夹下的模块来加载驱动,应该可以一并加载上。但是重启之后却发现之前上传的文件直接消失了!
这时我觉得这个这个目录应该不是一个真正位于磁盘上的目录,而只是内核虚拟出来的,真正的驱动文件应该另有存放位置,所以我直接在根目录下搜索了一下文件名包含ne1000的文件:
注意到还有很多相关的文件,而最后这个文件:
/vmfs/volumes/ea311779-c343e9f0-fdb8-e70146ecc34b/ne1000.v00
看起来更像是位于磁盘上的真实文件,所以就搜索了一下v00这个拓展名,找到了这么两个介绍:
https://www.v-front.de/2011/08/anatomy-of-esxi-50-installation-cd-and.html
https://polarclouds.co.uk/esxi7-missing-percs/
原来这些是以gz格式压缩后的设备驱动文件,并且esxi有一个专门的vmtar
命令用来在tar和这种文件中间进行转换:
vmtar -x ne1000.v00 -o ne1000.tar
就可以将上面的v00文件转换为tar文件
(这里为了便于查看将7z的显示模式调成了平铺模式,实际的目录类似于deb包,是可以在根目录下直接解压安装的)
开始魔改
可以看到这个文件中除了包含我们之前想修改的ne1000文件,还包含了两个用于描述驱动信息的文件,打开发现这两个文件中也包含着PCI ID的相关信息,所以也要一并改掉,修改完之后的三个文件效果如下:
ne1000:
ne1000.ids:
ne1000.map:
修改完之后上传回之前的目录,再用这三条命令重新打包回v00,覆盖原有的文件:
vmtar -c ne1000.tar -o ne1000.vgz
gzip ne1000.vgz
mv ne1000.vgz.gz ne1000.v00
ESXI 启动!
这下重启应该就大功告成了吧?没想到居然还是没认出来网卡!
于是我grep了一下vmkernel log:
cat /var/log/vmkernel.log |grep ne1000
发现了如下报错:
2023-12-06T16:00:25.179Z In(182) vmkernel: cpu0:524288)Loading ne1000.v00...
2023-12-06T16:00:25.179Z In(182) vmkernel: cpu0:524288)VisorFSTar: 2502: ne1000.v00 for 0xa4400 bytes
2023-12-06T16:00:26.194Z Al(177) vmkalert: cpu9:524494)ALERT: Failed to verify signatures of the following vib(s): [ne1000]. All tardisks validated
2023-12-06T16:00:27.501Z In(182) vmkernel: cpu6:524683)Loading module ne1000 ...
2023-12-06T16:00:27.502Z In(182) vmkernel: cpu6:524683)Elf: 2130: module ne1000 has license VMware
2023-12-06T16:00:27.504Z In(182) vmkernel: cpu6:524683)Device: 193: Registered driver 'ne1000-driver' from 46
2023-12-06T16:00:27.504Z In(182) vmkernel: cpu6:524683)DEBUG (ne1000): module loaded
2023-12-06T16:00:27.504Z In(182) vmkernel: cpu6:524683)Mod: 4830: Initialization of ne1000 succeeded with module ID 46.
2023-12-06T16:00:27.504Z In(182) vmkernel: cpu6:524683)ne1000 loaded successfully.
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)DEBUG (ne1000): attaching device 0x3e51430553405285
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)Device: 362: ne1000-driver:driver->ops.attachDevice :0 ms
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)Device: 368: Found driver ne1000-driver for device 0x3e51430553405285
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)DEBUG (ne1000): mapped BAR[0]: start = 4f900000, size = 20000, mapped to 4520801c0000
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)DEBUG (ne1000): rx FIFO size 20 KB, tx FIFO size 12 KB
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)DEBUG (ne1000): recv FIFO size 20 KB, xmit FIFO size 12 KB
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)DEBUG (ne1000): tx.maxFrame = 3968
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)DEBUG (ne1000): mmio = 4520801c0000, flashio = 0, portio = 0
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)DEBUG (ne1000): got port 0
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)DEBUG (ne1000): device ID: 8086:dc8:8086:0
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)DEBUG (ne1000): hw_addr = 0x4520801c0000, flash_addr = 0x4520801ce000
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)DEBUG (ne1000): setting mac type
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)INFO (ne1000): failed to identify hw with shared code
2023-12-06T16:00:27.505Z Al(177) vmkalert: cpu6:524683)ALERT: ALERT (ne1000): failed to identify hardware.
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)INFO (ne1000): failed to identify adapter for device 0x3e51430553405285
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)Device: 637: ne1000-driver:driver->ops.startDevice:0 ms
2023-12-06T16:00:27.505Z In(182) vmkernel: cpu6:524683)Device: 642: Device 0x3e51430553405285 start from driver ne1000-driver failed with bad0001
看起来已经很接近成功了,因为esxi内核已经尝试去加载这个驱动了,只是驱动内部可能还有代码逻辑来检测网卡id,导致识别失败。
这时就不得不请出IDA Pro了,直接把ne1000这个文件拖进去反编译:
IDA 启动!
根据上面的报错代码failed to identify hw with shared code
直接在在字符串中搜索:
交叉引用找到打印报错的函数:
__int64 __fastcall ne1000_hwIdentify(__int64 a1)
{
__int64 v2; // rdi
__int16 *v3; // rax
__int64 v4; // rdx
__int64 v5; // rcx
__int64 v6; // r8
int v7; // r9d
int v8; // eax
int v9; // ecx
int v10; // r8d
int v11; // r9d
int v12; // ebp
bool v13; // zf
__int64 v14; // rbp
int v15; // edx
int v16; // ecx
int v17; // r8d
int v18; // r9d
unsigned int v19; // r12d
int v20; // edx
int v21; // ecx
int v22; // r8d
int v23; // r9d
__int64 v24; // r12
int v25; // edx
int v26; // ecx
int v27; // r8d
int v28; // r9d
int v29; // edx
int v30; // ecx
int v31; // r8d
int v32; // r9d
__int64 v33; // r13
int v34; // edx
int v35; // ecx
int v36; // r8d
int v37; // r9d
int v38; // edx
int v39; // ecx
int v40; // r8d
int v41; // r9d
__int64 v42; // rdi
__int64 v43; // rbp
int v44; // edx
int v45; // ecx
int v46; // r8d
int v47; // r9d
int v48; // edx
int v49; // ecx
int v50; // r8d
int v51; // r9d
__int64 v52; // rdi
int v53; // ecx
int v54; // r8d
int v55; // r9d
char v57[4]; // [rsp+Ch] [rbp-70Ch] BYREF
char v58[32]; // [rsp+10h] [rbp-708h] BYREF
int v59; // [rsp+30h] [rbp-6E8h]
__int64 v60; // [rsp+40h] [rbp-6D8h]
__int64 v61[7]; // [rsp+198h] [rbp-580h]
int v62[56]; // [rsp+1D0h] [rbp-548h] BYREF
unsigned __int16 v63; // [rsp+2B2h] [rbp-466h]
char v64[168]; // [rsp+390h] [rbp-388h] BYREF
__int64 v65; // [rsp+438h] [rbp-2E0h]
ne1000_adapterGetInfo(*(_QWORD *)(a1 + 1848), v64);
v2 = v65;
*(_QWORD *)(a1 + 1856) = v65;
ne1000_deviceGetInfo(v2, v58);
ne1000_configRead(*(_QWORD *)(a1 + 1832));
v3 = *(__int16 **)(a1 + 1840);
v4 = v61[*v3];
*(_QWORD *)(a1 + 1928) = v4;
v5 = v61[v3[1]];
*(_QWORD *)(a1 + 1936) = v5;
v6 = v61[v3[2]];
*(_WORD *)(a1 + 1952) = v6;
ne1000_moduleLogFormat(
1,
(unsigned int)"DEBUG (ne1000): mmio = %lx, flashio = %lx, portio = %x\n",
v4,
v5,
(unsigned __int16)v6,
v7);
*(_QWORD *)(a1 + 1880) = v61[6];
*(_QWORD *)(a1 + 1864) = v60;
v8 = v59;
*(_DWORD *)(a1 + 1888) = v59;
if ( (unsigned int)(v8 - 36) <= 1 )
*(_QWORD *)(a1 + 1936) = *(_QWORD *)(a1 + 1928) + 57344LL;
*(_BYTE *)(a1 + 1352) = 0;
ne1000_deviceGetInfo(*(_QWORD *)(a1 + 1856), v62);
if ( v63 == 4284 )
goto LABEL_22;
if ( v63 <= 0x10BCu )
{
if ( v63 <= 0x1060u )
{
if ( v63 > 0x105Du )
goto LABEL_7;
LABEL_12:
v12 = 0;
goto LABEL_13;
}
v12 = 0;
if ( (unsigned __int16)(v63 - 4260) > 1u )
goto LABEL_13;
LABEL_22:
v12 = counterPort;
counterPort = (counterPort + 1) % 4;
goto LABEL_13;
}
if ( v63 == 4309 )
goto LABEL_22;
if ( v63 != 4313 )
goto LABEL_12;
LABEL_7:
v12 = 0;
if ( !(unsigned int)vmk_PCIReadConfig(*(unsigned int *)ne1000_module, *(_QWORD *)(a1 + 1864), 2LL, 14LL, v57)
&& v57[0] < 0 )
{
v12 = (*(_DWORD *)(*(_QWORD *)(a1 + 1928) + 8LL) >> 2) & 3;
}
LABEL_13:
ne1000_moduleLogFormat(1, (unsigned int)"DEBUG (ne1000): got port %d\n", v12, v9, v10, v11);
v13 = *(_BYTE *)(a1 + 1352) == 0;
*(_DWORD *)(a1 + 2040) = v12;
if ( v13 )
{
v43 = a1 + 1360;
v19 = ne1000_bridgeCreate(a1 + 1360, a1);
if ( !(_BYTE)v19 )
{
ne1000_moduleLogFormat(1, (unsigned int)"INFO (ne1000): failed to create bridge\n", v44, v45, v46, v47);
return v19;
}
if ( !(unsigned __int8)ne1000_bridgeIdentify(*(_QWORD **)(a1 + 1360)) )
{
ne1000_moduleLogFormat(
1,
(unsigned int)"INFO (ne1000): failed to identify hw with shared code\n",
v48,
v49,
v50,
v51);
LABEL_31:
v19 = 0;
ne1000_bridgeDestroy(v43);
return v19;
}
v52 = *(_QWORD *)(a1 + 1360);
*(_QWORD *)(a1 + 2048) = ne1000_sharedCodeOps;
ne1000_bridgeGetMACType(v52, v62);
LABEL_26:
ne1000_configRead(*(_QWORD *)(a1 + 1832));
switch ( v62[0] )
{
case 1:
case 2:
case 4:
case 5:
case 6:
*(_QWORD *)(a1 + 2056) = ne1000_legacyIOOps;
goto LABEL_33;
case 3:
case 7:
case 8:
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x14:
*(_QWORD *)(a1 + 2056) = ne1000_82574IOOps;
LABEL_33:
*(_BYTE *)(a1 + 1892) = 1;
return 1;
default:
ne1000_moduleLogFormat(1, (unsigned int)"INFO (ne1000): MAC (%d) not supported yet\n", v62[0], v53, v54, v55);
if ( *(_BYTE *)(a1 + 1352) )
{
v14 = a1 + 1368;
v24 = a1 + 1376;
v33 = a1 + 1384;
goto LABEL_37;
}
v43 = a1 + 1360;
break;
}
goto LABEL_31;
}
v14 = a1 + 1368;
v19 = ne1000_macCreate(a1 + 1368, a1);
if ( !(_BYTE)v19 )
{
ne1000_moduleLogFormat(1, (unsigned int)"INFO (ne1000): failed to create MAC data\n", v15, v16, v17, v18);
return v19;
}
if ( (unsigned __int8)ne1000_macIdentify(*(_QWORD *)(a1 + 1368)) )
{
v24 = a1 + 1376;
if ( (unsigned __int8)ne1000_phyCreate(a1 + 1376, a1) )
{
if ( (unsigned __int8)ne1000_phyIdentify(*(_QWORD *)(a1 + 1376)) )
{
v33 = a1 + 1384;
if ( (unsigned __int8)ne1000_nvmCreate(a1 + 1384, a1) )
{
if ( (unsigned __int8)ne1000_nvmIdentify(*(_QWORD *)(a1 + 1384)) )
{
v42 = *(_QWORD *)(a1 + 1368);
*(_QWORD *)(a1 + 2048) = ne1000_vmwareOps;
ne1000_macGetType(v42, v62);
goto LABEL_26;
}
ne1000_moduleLogFormat(1, (unsigned int)"INFO (ne1000): failed to identify NVM\n", v38, v39, v40, v41);
LABEL_37:
ne1000_nvmDestroy(v33);
}
else
{
ne1000_moduleLogFormat(1, (unsigned int)"INFO (ne1000): failed to create NVM data\n", v34, v35, v36, v37);
}
}
else
{
ne1000_moduleLogFormat(1, (unsigned int)"INFO (ne1000): failed to identify PHY\n", v29, v30, v31, v32);
}
ne1000_phyDestroy(v24);
}
else
{
ne1000_moduleLogFormat(1, (unsigned int)"INFO (ne1000): failed to create PHY data\n", v25, v26, v27, v28);
}
}
else
{
ne1000_moduleLogFormat(1, (unsigned int)"INFO (ne1000): failed to identify MAC\n", v20, v21, v22, v23);
}
v19 = 0;
ne1000_macDestroy(v14);
return v19;
}
可以看到是因为前面的ne1000_bridgeIdentify
函数返回错误了才会报错:
__int64 __fastcall ne1000_bridgeIdentify(_QWORD *a1)
{
__int64 v1; // rbp
__int16 PCIConfig16; // ax
__int64 v3; // rdx
int v4; // r9d
int v5; // r8d
int v6; // ecx
int v7; // r8d
int v8; // r9d
int v9; // edx
int v10; // ecx
int v11; // r8d
int v12; // r9d
int v13; // edx
int v14; // ecx
int v15; // r8d
int v16; // r9d
int v17; // edx
int v18; // ecx
int v19; // r8d
int v20; // r9d
int v22; // edx
int v23; // ecx
int v24; // r8d
int v25; // r9d
__int64 v26; // [rsp+0h] [rbp-2A8h] BYREF
unsigned __int16 v27; // [rsp+8h] [rbp-2A0h]
unsigned __int16 v28; // [rsp+Ah] [rbp-29Eh]
unsigned __int16 v29; // [rsp+Ch] [rbp-29Ch]
__int16 v30; // [rsp+10h] [rbp-298h]
__int64 v31; // [rsp+278h] [rbp-30h]
__int64 v32; // [rsp+280h] [rbp-28h]
ne1000_hwGetInfo(*a1, &v26);
*(_WORD *)(a1[1] + 9598LL) = HIWORD(v26);
*(_WORD *)(a1[1] + 9592LL) = v27;
*(_WORD *)(a1[1] + 9594LL) = v28;
*(_WORD *)(a1[1] + 9596LL) = v29;
*(_BYTE *)(a1[1] + 9600LL) = v30;
v1 = a1[1];
PCIConfig16 = ne1000_hwReadPCIConfig16(*a1, 4LL);
v3 = v31;
*(_WORD *)(v1 + 1238) = PCIConfig16;
*(_QWORD *)(a1[1] + 8LL) = v3;
v4 = v29;
v5 = v28;
v6 = v27;
*(_QWORD *)(a1[1] + 16LL) = v32;
ne1000_moduleLogFormat(1, (unsigned int)"DEBUG (ne1000): device ID: %0x:%x:%x:%x\n", HIWORD(v26), v6, v5, v4);
ne1000_moduleLogFormat(
1,
(unsigned int)"DEBUG (ne1000): hw_addr = %p, flash_addr = %p\n",
*(_QWORD *)(a1[1] + 8LL),
*(_QWORD *)(a1[1] + 16LL),
v7,
v8);
ne1000_moduleLogFormat(1, (unsigned int)"DEBUG (ne1000): setting mac type\n", v9, v10, v11, v12);
if ( (unsigned int)e1000_set_mac_type(a1[1], (int)"DEBUG (ne1000): setting mac type\n", v13, v14, v15, v16) )
return 0LL;
ne1000_moduleLogFormat(1, (unsigned int)"DEBUG (ne1000): setting init funcs\n", v17, v18, v19, v20);
if ( (unsigned int)e1000_setup_init_funcs(a1[1], 1LL) )
return 0LL;
ne1000_moduleLogFormat(1, (unsigned int)"DEBUG (ne1000): getting bus info\n", v22, v23, v24, v25);
if ( (unsigned int)e1000_get_bus_info(a1[1]) )
return 0LL;
*(_BYTE *)(a1[1] + 1119LL) = 0;
return 1LL;
}
而ne1000_bridgeIdentify
函数又会依次调用e1000_set_mac_type
、e1000_setup_init_funcs
和e1000_get_bus_info
,而后两个函数的日志似乎没有打印,可见应该是第一个e1000_set_mac_type
函数就出现了错误
__int64 __fastcall e1000_set_mac_type(__int64 a1, int a2, int a3, int a4, int a5, int a6)
{
unsigned __int16 v6; // cx
__int64 result; // rax
ne1000_bridgeDebugOutput((unsigned int)"e1000_set_mac_type", a2, a3, a4, a5, a6);
v6 = *(_WORD *)(a1 + 9592);
if ( v6 <= 0x10F6u )
{
if ( v6 > 0xFFFu )
{
switch ( v6 )
{
case 0x1000u:
*(_DWORD *)(a1 + 268) = 1;
result = 0LL;
break;
case 0x1001u:
case 0x1004u:
*(_DWORD *)(a1 + 268) = 2;
result = 0LL;
break;
case 0x1008u:
case 0x1009u:
case 0x100Cu:
case 0x100Du:
*(_DWORD *)(a1 + 268) = 3;
result = 0LL;
break;
case 0x100Eu:
case 0x1015u:
case 0x1016u:
case 0x1017u:
case 0x101Eu:
*(_DWORD *)(a1 + 268) = 4;
result = 0LL;
break;
case 0x100Fu:
case 0x1011u:
*(_DWORD *)(a1 + 268) = 5;
result = 0LL;
break;
case 0x1010u:
case 0x1012u:
case 0x101Du:
*(_DWORD *)(a1 + 268) = 7;
result = 0LL;
break;
case 0x1013u:
case 0x1014u:
case 0x1018u:
*(_DWORD *)(a1 + 268) = 9;
result = 0LL;
break;
case 0x1019u:
case 0x101Au:
*(_DWORD *)(a1 + 268) = 11;
result = 0LL;
break;
case 0x1026u:
case 0x1027u:
case 0x1028u:
*(_DWORD *)(a1 + 268) = 6;
result = 0LL;
break;
case 0x1049u:
case 0x104Au:
case 0x104Bu:
case 0x104Cu:
case 0x104Du:
case 0x10C4u:
case 0x10C5u:
goto LABEL_44;
case 0x105Eu:
case 0x105Fu:
case 0x1060u:
case 0x10A4u:
case 0x10A5u:
case 0x10BCu:
case 0x10D5u:
case 0x10D9u:
case 0x10DAu:
*(_DWORD *)(a1 + 268) = 13;
result = 0LL;
break;
case 0x1075u:
*(_DWORD *)(a1 + 268) = 12;
result = 0LL;
break;
case 0x1076u:
case 0x1077u:
case 0x1078u:
case 0x107Cu:
*(_DWORD *)(a1 + 268) = 10;
result = 0LL;
break;
case 0x1079u:
case 0x107Au:
case 0x107Bu:
case 0x108Au:
case 0x1099u:
case 0x10B5u:
*(_DWORD *)(a1 + 268) = 8;
result = 0LL;
break;
case 0x107Du:
case 0x107Eu:
case 0x107Fu:
case 0x10B9u:
*(_DWORD *)(a1 + 268) = 14;
result = 0LL;
break;
case 0x108Bu:
case 0x108Cu:
case 0x109Au:
*(_DWORD *)(a1 + 268) = 15;
result = 0LL;
break;
case 0x1096u:
case 0x1098u:
case 0x10BAu:
case 0x10BBu:
*(_DWORD *)(a1 + 268) = 18;
result = 0LL;
break;
case 0x10A7u:
case 0x10A9u:
case 0x10D6u:
*(_DWORD *)(a1 + 268) = 27;
result = 0LL;
break;
case 0x10BDu:
case 0x10BFu:
case 0x10C0u:
case 0x10C2u:
case 0x10C3u:
case 0x10CBu:
case 0x10CCu:
case 0x10CDu:
case 0x10CEu:
case 0x10E5u:
case 0x10F5u:
goto LABEL_23;
case 0x10C9u:
case 0x10E6u:
case 0x10E7u:
case 0x10E8u:
goto LABEL_33;
case 0x10D3u:
case 0x10F6u:
*(_DWORD *)(a1 + 268) = 16;
result = 0LL;
break;
case 0x10DEu:
case 0x10DFu:
goto LABEL_34;
case 0x10EAu:
case 0x10EBu:
case 0x10EFu:
case 0x10F0u:
*(_DWORD *)(a1 + 268) = 22;
result = 0LL;
break;
default:
return 4294967291LL;
}
return result;
}
if ( v6 <= 0x440u )
{
if ( v6 > 0x437u && ((1LL << ((unsigned __int8)v6 - 56)) & 0x115) != 0 )
{
LABEL_9:
*(_DWORD *)(a1 + 268) = 29;
return 0LL;
}
return 4294967291LL;
}
if ( v6 == 3411 )
{
LABEL_13:
*(_DWORD *)(a1 + 268) = 25;
return 0LL;
}
if ( v6 > 0xD53u )
{
if ( v6 == 3413 )
goto LABEL_13;
return 4294967291LL;
}
result = 4294967291LL;
if ( (unsigned __int16)(v6 - 3404) > 3u )
return result;
LABEL_18:
*(_DWORD *)(a1 + 268) = 26;
return 0LL;
}
if ( v6 > 0x15FCu )
{
if ( v6 > 0x1F41u )
{
if ( v6 == 10572 )
{
LABEL_23:
*(_DWORD *)(a1 + 268) = 20;
return 0LL;
}
return 4294967291LL;
}
if ( v6 > 0x1F3Fu )
{
*(_DWORD *)(a1 + 268) = 31;
return 0LL;
}
result = 4294967291LL;
if ( (unsigned __int16)(v6 - 6684) <= 3u )
goto LABEL_18;
}
else
{
if ( v6 <= 0x1500u )
return 4294967291LL;
switch ( v6 )
{
case 0x1501u:
LABEL_44:
*(_DWORD *)(a1 + 268) = 19;
result = 0LL;
break;
case 0x1502u:
case 0x1503u:
*(_DWORD *)(a1 + 268) = 23;
result = 0LL;
break;
case 0x150Au:
case 0x150Du:
case 0x1518u:
case 0x1526u:
LABEL_33:
*(_DWORD *)(a1 + 268) = 28;
result = 0LL;
break;
case 0x150Cu:
*(_DWORD *)(a1 + 268) = 17;
result = 0LL;
break;
case 0x150Eu:
case 0x150Fu:
case 0x1510u:
case 0x1511u:
case 0x1516u:
case 0x1527u:
goto LABEL_9;
case 0x1521u:
case 0x1522u:
case 0x1523u:
case 0x1524u:
case 0x1546u:
*(_DWORD *)(a1 + 268) = 30;
result = 0LL;
break;
case 0x1525u:
LABEL_34:
*(_DWORD *)(a1 + 268) = 21;
result = 0LL;
break;
case 0x1533u:
case 0x1534u:
case 0x1535u:
case 0x1536u:
case 0x1537u:
case 0x1538u:
case 0x157Bu:
case 0x157Cu:
*(_DWORD *)(a1 + 268) = 32;
result = 0LL;
break;
case 0x1539u:
*(_DWORD *)(a1 + 268) = 33;
result = 0LL;
break;
case 0x153Au:
case 0x153Bu:
case 0x1559u:
case 0x155Au:
case 0x15A0u:
case 0x15A1u:
case 0x15A2u:
case 0x15A3u:
*(_DWORD *)(a1 + 268) = 24;
result = 0LL;
break;
case 0x156Fu:
case 0x1570u:
case 0x15B7u:
case 0x15B8u:
case 0x15B9u:
case 0x15D6u:
case 0x15D7u:
case 0x15D8u:
case 0x15E3u:
goto LABEL_13;
case 0x15BBu:
case 0x15BCu:
case 0x15BDu:
case 0x15BEu:
case 0x15F4u:
case 0x15F5u:
case 0x15F9u:
case 0x15FAu:
case 0x15FBu:
case 0x15FCu:
goto LABEL_18;
default:
return 4294967291LL;
}
}
return result;
}
这个函数中充满了大量的switch-case,可见确实是在对网卡ID进行判断,我们找到原本I219V-19应该进入的分支:
发现只要将上面的0xD4C改为比0xDC8更大的数就可以正常的网卡进入LABLE_18后面的代码
在使用IDA patch这一处代码之后重新制作v00文件并上传覆盖,重启之后ESXI终于认出了网卡:
后记
在b站上看到有UP主教多久如何更改网卡的eeprom来修改网卡的PCI ID,但是评论区有很多人表示容易把网卡刷坏,那么我这里就提供一种纯软件的解决方法。
感谢你看到这里,如果你并不想像我这样折腾也可以直接下载我patch好的v00文件,只要覆盖掉原本的ne1000.v00后重启即可:
https://download.csdn.net/download/qq_33917045/88611191