📄 add_slic.asm
字号:
;//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
; Vista Add-SLIC Module For AMI BIOS
; 功能:为了实现Microsoft Vista的免激活(OEM形式的激活),该模块给BIOS添加上相应的SLIC。只需要再使用对应Vista版本
; 的OEM版的KEY和对应SLIC中的品牌的证书,就可以实现Microsoft Vista的免激活。
;
; 使用方法:
; 1、用MMTOOL打开AMI BIOS以.ROM形式保存的文件,找到其中的ID=20的模块,释放这些模块,然后用WINHEX或者ULTRA
; EDIT打开这些模块,搜索“PXE”、“NETWORK”、“ETHERNET”等字符串,只要找到其中的一个,就可以确定这个模块是网卡
; 的BOOT ROM。在该模块的搜索“PCIR”,其后面的数据假设为YYXX BBAA形式,其中:
; XXYY(注意都是倒写的)=VENDOR ID AABB = DEVICE ID
; 将上面的值填写到下面的PCI_VENDOR_ID、PCI_DEVICE_ID处,然后编译成.bin文件。然后用MMTOOL的替换功能将该BIN文件替换
; 原来的网卡的BOOT ROM(一定要替换网卡的BOOT ROM)。
;
; 2、将修改后的该.rom文件刷进主板的CMOS后,重新开机,按DEL、F1、F2或者其他键进入CMOS设置,在“BOOT”(或其他类似
; 的)菜单中,一定要将“ SLIC Mod”设置在“HARD DRIVE”的前面。按F10保存就可以了!
; 如果找不到“SLIC Mod”,如果有“LAN”之类的与网络有关的字样,把它设置在“HARD DRIVE”前面,还要修改“Integrated
; Peripherals”(整合周边设备设定)中的“Onboard LAN Option ROM”设置为“Enabled”。
;
; 3、该模块也可以应用于AWARD,修改VENDOR ID、DEVICE ID后,直接执行cbrom xxx.rom /pci add_slic.mod就可以了。
; 这样会直接替换掉原来的BOOT ROM。
;
; 4、如果启用了该模块后,会黑屏(不是那种刷了BIOS就黑屏的情况),这时,仅需要在CMOS设置中将该模块禁用就行了。
;
; 5、有些特殊的BIOS,即带有MINIT、GV3情况的BIOS,请检查原始的网卡的BOOT ROM是否在其后面,如果在后面,可以放心刷,
; 如果不是,最好不要用。
;
;
; 注意:刷BIOS必然有风险,在使用该模块之时,使用者必须自行承担该风险,本模块的开发者不承担解决风险的责任。
; 声明:本模块开发者开拔该模块,是为了方便某些主板的用户给BIOS添加SLIC功能,并非是为了鼓励使用盗版!
; 如经济许可,请支持正版!
;
; 开发者:
; 核心技术 XBXCC @VistaFans
; SLIC添加功能实现[A M I] dkpnop[nopworld] @VistaFans
;//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
use16 ; 16-bit by default
ROM_BLOCK = 03H ;block
ROM_SIZE = ROM_BLOCK * 512
PCI_VENDOR_ID = 1011h ;VirtualPC=[VID= 1011 h, DID= 0009 h] vmware(amd am79c970a)=[1022h,2000h]
PCI_DEVICE_ID = 0009h ;
PCI_CLASS_CODE0 = 02h
PCI_CLASS_CODE1 = 00h
PCI_CLASS_CODE2 = 00h
pci_rom_header_start:
pci_rom_signature dw 0AA55H ;Always equal to AA55h
pci_rom_init_size db ROM_BLOCK ;Size in 512 byte blocks
;pci_rom_init_entry dd ? ;JMP instruction (entry point for init)
CALL INIT ;绝对不可以一个retf了事,不然,会在BIOS
RETF ;的BOOT设置中看不到PnPIC_Prod_STR所代表的内容
pci_rom_reserved db 11h dup (00h)
pci_rom_data_struc_ptr dw pci_rom_data_struc_start ;Offset of PCI ROM Data Structure
pci_rom_pnp_struc_ptr dw pci_pnp_inst_check_start ;offset of PCI ROM PnP Data Structure
;pci_rom_header_end
times (0x10-($ mod 0x10)) db 0
pci_rom_data_struc_start:
pcird_signature dd 'PCIR' ;Should equal to PCIR_SIGNATURE
pcird_vendid dw PCI_VENDOR_ID ;PCI Vendor ID
pcird_devid dw PCI_DEVICE_ID ;PCI Device ID
pcird_vpd_ptr dw 0000h ;Pointer to Vital Product Data struc
pcird_struc_len dw 0018h ;Length of this structure (18h)
pcird_struc_rev db 00h ;Revision number of this structure (00)
pcird_base_type db PCI_CLASS_CODE0 ;Class code - base type
pcird_sub_type db PCI_CLASS_CODE1 ;Class code - sub type
pcird_if_type db PCI_CLASS_CODE2 ;Class code - interface type
pcird_image_len dw ROM_BLOCK ;Length of this ROM image/512
pcird_code_rev dw 0000h ;Vendor defined rev level of ROM code
pcird_code_type db 00h ;Type of code in image (see equ's below)
pcird_indicator db 80h ;Indocator flags (see equ's below)
pcird_reserved dw 0000h
;pci_rom_data_struc_end
times (0x10-($ mod 0x10)) db 0
pci_pnp_inst_check_start:
PnPIC_Signature db '$PnP'
PnPIC_Revision db 01h ;01=PCI 2.0
PnPIC_Length db 02 ;2*16h
PnPIC_ControlFlags dw 0000h ;offset to next header (0 = none)
PnPIC_Reserved db 00h ;reserved data
PnPIC_CheckSum db 00h ;PnP structure checksum
PnPIC_Dev_Identifier dd 00000000h ;device identifier
PnPIC_Manu_STR_Offset dw PnPIC_Manu_STR ;pointer to manufacturer string
PnPIC_Prod_STR_Offset dw PnPIC_Prod_STR ;pointer to productname string
PnPIC_Dev_Class_Code_0 db PCI_CLASS_CODE0 ;Class code - base type
PnPIC_Dev_Class_Code_1 db PCI_CLASS_CODE1 ;Class code - sub typ
PnPIC_Dev_Class_Code_2 db PCI_CLASS_CODE2 ;Class code - interface type
PnPIC_Dev_Indicator db 0e4h ;device indicators (64h - shadowable,cacheable,not only for boot,IPL device)
PnPIC_Boot_Conn_Vector dw 0000h ;boot connection vector (0-none)
PnPIC_Disconn_Vetor dw 0000h ;disconnect vector (0-none)
PnPIC_Bootstrar_Vetor dw BOOTSTRAP ;bootstrap entry vector (0-none)
PnPIC_Reserved_DATA dw 0000h ;reserved data
PnPIC_Info_Vector dw 0000h ;static resource info vector (0-none)
;pci_pnp_inst_check_end
;****************************************
PnPIC_Manu_STR DB "China",00h ;后面一定要加00h,这代表字符串结束!
PnPIC_Prod_STR DB "SLIC Mod",00h ;在BIOS的BOOT设置中看到的字符串!
;****************************************
times (0x10-($ mod 0x10)) db 0
PREV_CHKSUM = 0
repeat 20H ;20H= Repeat count !
load CHKSUM byte from pci_pnp_inst_check_start+%-1
CHKSUM = (PREV_CHKSUM + CHKSUM) mod 0x100
PREV_CHKSUM = CHKSUM
end repeat
store byte (0x100-CHKSUM) at (pci_pnp_inst_check_start+9h)
times (0x10-($ mod 0x10)) db 0
INIT: ;这时的CS是可以写数据的!因为BIOS解压各模块时,各模块都设置为可写状态!
retn
BOOTSTRAP: ;这时的CS是绝对不可以写数据!必须另外想办法写!可以用堆栈!
pushad ;必须使用BOOTSTRAP,是因为,ACPI很大程度上是在该PCI模块运行后,才生成的。
push ds ;经过多次的失败,证明了必须用BOOTSTRAP来解决!
push es
xor ecx,ecx
mov al,1
call setRealMode ;enter bigrealmode
push ecx
call main
pop ecx
xor al,al
call setRealMode
pop es
pop ds
popad
retf ;return to this rom's header
;//////////////////////////////////////////////////////////////////////////////////////////
;//////////////////////////////////////////////////////////////////////////////////////////
enableA20:
in al,92h
test al,02h
jne A20_BE_OPEN
or al,02h
out 92h,al
retn
A20_BE_OPEN:
mov cl,01h
retn
disableA20:
in al,92h
cmp cl,01h
je D_A20_EXIT
and al,0fdh
out 92h,al
D_A20_EXIT:
retn
setRealMode:
push eax
cli
or al,al
jz short offA20;
call enableA20
jmp enable4gb;
offA20:
call disableA20
enable4gb:
push ecx
;--------------------下面使用堆栈的方法因为部分AWARD主板的8800:AE00等区域是只读的,所以必须用回堆栈---------
xor eax,eax
xor ecx,ecx ;计算cs:GDT1的物理地址,用于LGDT
mov ax,cs ;
shl eax,4h ;
mov cx,GDT1 ;这里使用堆栈操作,可以不用考虑不可以改写伪GDTR的值的问题
add eax,ecx
push eax
mov ax,GDT1_END-GDT1-1h
push ax
mov di,sp ;这里用堆栈来保存伪GDTR的值
add sp,6h ;恢复原来的堆栈指针!6h = 伪GDTR的长度
lgdt [ss:di] ;如果PC反复重启,绝大多数情况,是因为GDTR没有设置好。
;-----------------------------------------------------------------------------------------------------------
; xor eax,eax
; xor ecx,ecx
; mov ax,08800h ;这里使用8800:AE00区域存放临时的伪GDTR
; mov di,0ae00h ;8800:AE00这个数据来源于还原卡
; push di ;记得将DI进栈,以保留DI的指向。
; mov es,ax ;
; mov si,GDTR ;伪GDTR的格式需要在ASM后面事先写好,这样可以省一些处理代码
; mov cx,06h
; rep movs byte [di],[cs:si]
; pop di ;DI出栈
; mov ax,cs ;
; shl eax,4h ;
; mov cx,GDT1
; add eax,ecx ;这个EAX就是GDT1的物理地址
; mov [es:di+2h],eax
; lgdt [es:di] ;如果PC反复重启,绝大多数情况,是因为GDTR没有设置好。
;---------------------------------------------------------------------------------------------------------------
mov eax,cr0
or al,1
mov cr0,eax ;enter protected mode
jmp pm_flush_queue
pm_flush_queue:
pop ecx
pop eax
push eax
push ecx
or al,al
jz short to64k
mov ax,DATA4G_INDEX
jmp short enable4gbOK
to64k:
mov ax,DATA64K_INDEX
enable4gbOK:
mov dl,al
mov es,ax
mov ds,ax
mov eax,cr0
and al,0feh
mov cr0,eax
jmp rm_flush_queue ;clear CPU instruction queue
rm_flush_queue:
xor ax,ax
mov dh,al
mov ds,ax
mov es,ax
sti ;恢复中断
pop ecx
pop eax
retn
main:
call S_RSD_PTR_
jb UNdo_1 ;if < jmp to undo
call find_enough_slic_space ;al的定义:将AL转换成2进制,如: 10H(00010000),aXY这里设置为标志位
jb not_ori_slic ;x=(0,支持ACPI规范[2.0+];1,不支持) a xy
call public_function ;y=(0,原生BIOS;1,非原生BIOS)
UNdo_1:
retn
not_ori_slic:
call s_support_ACPI
call public_function
Undo_2:
retn
public_function:
call copy_slic_to_edi
add al,10h ;保留AL的标志位,+10=带标志位的RSDT地址在RSD PTR中的偏移
call public_table_function
add al,8h ;保留AL的标志位,+10=带标志位的xsdt地址在RSD PTR中的偏移
call public_table_function
retn
public_table_function:
push esi
push edi
movzx ebx,al ;将AL扩展成32位的EBX,变成000000AL
and bl,18h ;清除BL的标志位,即还原成真正的偏移
mov esi,[esi+ebx] ;esi = rsdt_address or xsdt_address !
test al,1h ;检查AL中的Y是否为0
je public_table_function_is_ori_bios ;如果为0,则表明该BIOS是原生的,原生BIOS肯定支持ACPI 2.0+
mov ecx,[esi+4h]
xor ebx,ebx
lea edx,[esi+ecx]
test al,8h ;检查AL中的a是否为0(18H=0001 1000)(0001a0xy)
je public_table_function_is_rsdt_table ;如果为0,则表明调用的AL=带标志位的rsdt地址在RSD PTR中的偏移
test al,2h ;检查AL中的x是否为0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -