利用BIOS的硬件信息编程(1)
1.为什么要有BIOS这个东西
BIOS实际就是ROM里面的一段小程序(芯片总容量大概就是几M),在主板通电时候会硬件加载执行。基本功能就是进行硬件检测,检查没问题就引导bootloader和系统。
为什么需要这个?
第一个原因,即使只有一块主板,什么外部连接的存储介质(磁盘,U盘等存储)都没有(更别说操作系统),这种情况下,一个主板其实也应该能进行一些硬件检查( 甚至是设置),这就是BIOS存在并且嵌入到主板的一个原因。再者,不同主板不一样的硬件配置,对应的bios代码也不一样。不过两个不同bios,对外提供统一的一些统一的操作硬件的接口,他们遵循bios规范【http://blog.chinaunix.net/uid-27033491-id-3239348.html】,以前的操一些操作系统例如DOS就是直接使用bios提供的硬件接口访问硬件,现在的linux访问硬件就是绕过bios访问硬件,下面我们会测试通过bios去访问硬件。
2.bios加载MBR扇区
首先主板通电,硬件自动加载bios程序。bios程序检查硬件,初始化和设置硬件,然后加载磁盘(启动盘)的MBR扇区到0x7c00,然后跳到0x7c00执行。为什么是0x7c00?可以看【http://www.ruanyifeng.com/blog/2015/09/0x7c00.html】。主要是兼容历史的原因。
3.什么是启动扇区?
一个磁盘分为多个磁面,一个磁面一个head(读写磁头),一个磁面多个磁道(track),一个磁道多个扇区(sector),一个扇区512字节。其中0磁头0磁盘第一个扇区称为这个磁盘的第一个扇区。如果这个扇区(512字节)最后两个字节是0xaa55.识别这个扇区是MBR主启动扇区。
现在我们就来测试一下bios去加载MBR扇区的流程。
我们这里使用redhat7.2的qemu虚拟化来做实验最为简单。
首先新建一块1G的虚拟磁盘:
qemu-img create -f qcow2 /home/disk.qcow2 2G
使用已有磁盘新建一台虚拟机,启动虚拟机,查看屏幕输出信息:
现在设置磁盘的第一个扇区为启动扇区MBR.
#vim mbr.asm
start:
times (510-($-$$)) db 0 ;510字节前面都设置为0,$表示当前地址,$$表示起始地址
dw 0xaa55 ;511和512字节设置为AA55,表示启动扇区
编译:nasm mbr.asm -o mbr
这个文件现在我们的磁盘的第一个扇区:
由于qcow2是一个虚拟磁盘文件。我们需要通过nbd把虚拟磁盘文件挂在为真正可以访问的磁盘的。默认centos是没有nbd 安装nbd驱动。
这里需要编译一下内核的nbd驱动:
查看内核版本:
# uname -a
Linux bogon 3.10.0-327.el7.x86_64 #1 SMP Thu Nov 19 22:10:57 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
#wget http://vault.centos.org/7.2.1511/os/Source/SPackages/kernel-3.10.0-327.el7.src.rpm
#rpm2cpio kernel-3.10.0-327.el7.src.rpm |cpio -imd
#tar xvf linux-3.10.0-327.el7.tar.xz
增加内核编译选项
Device Drivers --->
[*] Block devices --->
<M> Network block device support
# make
#insmod drivers/block/nbd.ko max_part=8
# qemu-nbd -c /dev/nbd0 /home/disk.qcow2 ----------------虚拟磁盘文件挂在为真正的磁盘设备
# dd if=./mbr of=/dev/nbd0 bs=1 count=512 ----------------把上面的程序mbr写入磁盘的头512字节,也就是第一个扇区
#qemu-nbd -d /dev/nbd0
重启启动虚拟机,虚拟机的屏幕输出:
这说明bios已经识别到磁盘的MBR分区并且已经把MBR分区加载到了0x7c00地址执行。
3.利用执行MBR扇区的代码实现键盘操作功能。
现在处理器的控制权已经在mbr扇区代码的手里。现在我们就可以通过mbr扇区的代码去控制我们的处理器,进而操作我们的主板。
现在我们就实现键盘的操作功能,其实bios已经有相关的键盘的接口提供。但是我们目前先不用它的接口。我们直接操作我们的键盘。
目前我的键盘是ps2接口的键盘, 使用的ps2控制器是Intel的8042.
所以我们先链接一下ps2接口,以及连接的电路图。
键盘链接ps2插头:
电脑ps2控制器连接图:
上面两个图整合为一个整体就是:
我们cpu可以控制ps2控制器8042进而控制我们的键盘。所以我们需要了解一下ps2的协议以及8042的芯片资料。其中ps2协议可以了解一下时钟信号和数据信号(电信号)的一些传输协议,当然这些信号我们只需要了解就行,因为这些信号ps2控制器可以帮我们处理,我们只要操作ps2控制器。ps2协议可以自己百度,这里只提供一下数据传输的信号:
电信号采集数据要不就是高电平(二进制1),要不就是低电平(二进制0),上面8个数据刚好可以组成一个字节的数据。控制器就是通过这些信号和键盘进行通信的。当然,这是控制器的工作,我们可以重点不放在这里【有兴趣可以自己百度一下"ps2协议"或者"ps2 protocol"】。我们重点看如何操作ps2控制器。现在我们看一下8042控制器的操作:
这里有一篇不错的介绍文章:http://blog.chinaunix.net/uid-25099259-id-3409632.html
8042控制器的寄存器有四个:状态寄存器,输出缓存控制器,输入缓冲控制器,控制寄存器。我们通过处理器操作端口就可以控制8042寄存器:
IO Port | Access Type | Purpose |
---|---|---|
0x60 | Read/Write | Data Port |
0x64 | Read | Status Register |
0x64 | Write | Command Register |
关于寄存器的 每一个位的意思,可以看一下这个文章【http://wiki.osdev.org/%228042%22_PS/2_Controller】,里面有详细的寄存器信息介绍,还有如何初始化和使用控制器。我们就参考这边文章来操作的我们的寄存器。由于汇编不好,代码可能写的有点不精简。
开始之前我们需要先要调试工具。例如读取到数据我们如何知道数据是什么?
通过显示是最直观的。显示暂时没有去研究,我们可以直接使用bios提供的显示接口。例如打印0xaa,怎么打印?代码如下
代码写的有点挫,熟悉的人可以修改一下:
start: jmp run
tran_ascii:;数字转为对应的ASCIIcmp al,9jle add_30hjmp add_57h
add_30h:add al,0x30;eg:0的ASCII 0x30ret
add_57h:add al,0x57;eg:a的ASCII 0x61ret
print_8bit:;dl has data need print,eg:0xABpush axpush bxpush cxpush dxxor ax,ax ;clearxor bx,bxmov al,dl ;被除数mov bl,16 ;除数div bl;AL存储除法操作的商,AH存储除法操作的余数;把要打印的数据先保存起来mov di,need_printstosw;显示高四位mov ah,0x09mov bh,0 ;显示页码mov cx,1 ;重复输出字符的次数call tran_asciiint 0x10;功能描述:在当前光标处按指定属性显示字符;移动光标到下一处mov ah,0x03;读取当前光标位置int 0x10add dl,1;移动光标到下一处mov ah,0x02mov bh,0int 0x10;显示低四位mov si,need_printlodswmov al,ahmov ah,0x09mov cx,1 ;call tran_asciiint 0x10pop dxpop cxpop bxpop axretneed_print: DW 0x00
run:mov dl,0x1bcall print_8bittimes (510-($-$$)) db 0
有了这个我们就可以打印出控制器端口读出来的数据了。下面开始真正编码操作ps2控制器:
start: jmp run
;
;数字转为对应的ASCII
tran_ascii:cmp al,9jle add_30hjmp add_57h
add_30h:add al,0x30;eg:0的ASCII 0x30ret
add_57h:add al,0x57;eg:a的ASCII 0x61retprint_8bit:push axpush bxpush cxpush dx;dl has data need print,eg:0xABxor ax,ax ;clearxor bx,bxmov al,dl ;被除数mov bl,16 ;除数div bl;AL存储除法操作的商,AH存储除法操作的余数;savemov di,need_printstosw;移动光标到下一处mov ah,0x03;读取当前光标位置int 0x10add dl,1;移动光标到下一处mov ah,0x02mov bh,0int 0x10;显示high四位mov si,need_printlodswmov ah,0x09mov bh,0 ;显示页码mov cx,1 ;重复输出字符的次数call tran_asciiint 0x10;功能描述:在当前光标处按指定属性显示字符;移动光标到下一处mov ah,0x03;读取当前光标位置int 0x10add dl,1;移动光标到下一处mov ah,0x02mov bh,0int 0x10;显示low四位mov si,need_printlodswmov al,ahmov ah,0x09mov cx,1 ;call tran_asciiint 0x10pop dxpop cxpop bxpop axret
wait_data:in al,0x64and al,1bjz wait_datain al,0x60retneed_print: DW 0x00run:cli;Disable Devicesmov al,0xadout 0x64,al;Flush The Output Buffer
flush_data:in al,0x64and al,0x01jz flush_okin al,0x60jmp flush_data
flush_ok:;Set the Controller Configuration Byte mov al,0x20;read configure out 0x64,alin al,0x60mov dl,aladd dl,11101100b;disabled interrupt,use poll modemov al,0x60;set configureout 0x64,almov al,dlout 0x60,al;Perform Controller Self Testmov al,0xaaout 0x64,alcall wait_datacmp al,0x55jne err;Enable Devicesmov al,0xae ;first port for keyboardout 0x64,al
test_port_1:mov al,0xABout 0x64,alcall wait_datacmp al,0x00jne err
read_input:call wait_data mov dl,alcall print_8bitjmp read_input
err:times (510-($-$$)) db 0dw 0xaa55
上面就是键盘输入:bear和ctl+alt的扫描码输出。
各个按键的扫描码可以查看:http://wiki.osdev.org/PS/2_Keyboard
0x30 | B pressed |
0xB0 | B released |
0x12 | E pressed |
0x92 | E released |
0x1E | A pressed |
0x9E | A released |
0x13 | R pressed |
0x93 | R released |
0x1D | left control pressed |
0x38 | left alt pressed |
0xB8 | left alt released |
0x9D | left control released |
利用BIOS的硬件信息编程(1)相关推荐
- 计算机开机硬件检查,开机bios检测硬件信息方法
你们知道怎么设置电脑开机检测硬件信息吗,下面是学习啦小编带来开机bios检测硬件信息方法的内容,欢迎阅读! 开机bios检测硬件信息方法: 电脑组装完成即便不装操作系统也可以进行加电测试,在开机自检的 ...
- 计算机硬件信息被修改怎么还原,修改bios硬件信息方法
你们知道怎么BIOS的硬件信息怎么修改吗?下面是学习啦小编带来修改bios硬件信息方法的内容,欢迎阅读! 修改bios硬件信息方法: 按下主机箱上的开机键,在电脑出现第一屏幕信息时,屏幕会有进入CMO ...
- C# 读取电脑硬件信息
我们有时遇到安装软件需要授权文件,就是利用电脑的硬件信息,来创建的授权文件的.加密和解密是很复杂的,可以独立一篇文章介绍一下,本文具体介绍C#获取电脑硬件信息,例如CPU信息,硬盘信息,RAM信息,主 ...
- linux 查看硬件 工具,linux下查看硬件信息方法
想知道怎么查看电脑的硬件信息吗,下面是学习啦小编带来linux下查看硬件信息方法的内容,欢迎阅读! linux下查看硬件信息方法: 建议直接进主板的bios查看硬件信息 linux的话看具体什么版本了 ...
- 使用WMI编程获取主机硬件信息(CPU_ID,硬盘、主板、BIOS序列号,Mac地址)
最近在公司实习,有个应用需要获取windows主机的一些硬件信息,在网上查阅了一些资料,大部分都是使用WMI编程来实现的. 因此小菜鸟自己也用WMI实现了一下,封装为函数GetUserInfo(),具 ...
- C#获取电脑硬件信息(CPU ID、主板ID、硬盘ID、BIOS编号
C#获取电脑硬件信息(CPU ID.主板ID.硬盘ID.BIOS编号 http://www.cnblogs.com/liufei88866/archive/2010/05/11/1732671.htm ...
- c 获取计算机相关信息,C#编程获取各种电脑硬件信息的方法示例
本文实例讲述了C#编程获取各种电脑硬件信息的方法.分享给大家供大家参考,具体如下: 获取CPU编号: ManagementClass mc = new ManagementClass("Wi ...
- 联想台式计算机的设备序列号,WMI获取硬件信息封装函数方法(联想台式机出厂编号 CPUID BIOS序列号 硬盘信息 显卡信息 MAC地址)...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都是可以提取出来的,就自己把那些公共部分提出出来,以后如果要获取某部分的硬件信息就不用写一个一个的函数,比如获取MAC地址就写一个获取MAC地 ...
- html显示器对象属性,Web网站中利用JavaScript中ActiveXObject对象获取硬件信息(显示器数量、分辨率)从而进行单双屏跳转...
前言:最近这两天工作上,要实现一个功能,在好友阿聪的帮助下,算是比较好的解决了这个需求. B/S的Web网站,需要实现点击按钮时,根据客户端连接的显示屏(监视器)数量进行,单双屏跳转显示新页面. 由于 ...
最新文章
- 28天打造专业红客(一)
- 反对网抄,没有规则可以创建目标install 靠谱解答
- 设计模式:访问者(Visitor)模式
- 简单了解Python网络爬虫
- java MySQL mq_蚂蚁社招Java岗面试分享(MySQL+RabbitMQ+Spring Boot)
- Springboot2 自定义异常处理
- arraylist扩容是创建新数组吗 java_Java ArrayList扩容问题实例详解
- python新手入门基础操作谨记这5点_Python大牛指点新手之:掌握这5点,可以快速从入门到进阶!...
- MiluGPS(迷路者GPS导航软件)
- java项目-第35期在线购书商城系统【毕业设计】
- 最有效的清理C盘/win10如何给系统盘瘦身
- iOS申请邓白氏总结
- rs.next()的理解
- blender 2.8的基本使用和使用形态键(Shape key)做帧动画
- LRC歌词制作LRC歌词制作
- [R语言] 生成随机数
- 快速上手云原生安全平台 NeuVector
- 基本函数依赖和候选键_[总结]关系数据库设计基础(函数依赖、无损连接性、保持函数依赖、范式、……)...
- 数据库单个插入操作转为批量插入
- 计算机30秒自动更换的桌面软件,电脑壁纸自动更换(SyncWall)