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)相关推荐

  1. 计算机开机硬件检查,开机bios检测硬件信息方法

    你们知道怎么设置电脑开机检测硬件信息吗,下面是学习啦小编带来开机bios检测硬件信息方法的内容,欢迎阅读! 开机bios检测硬件信息方法: 电脑组装完成即便不装操作系统也可以进行加电测试,在开机自检的 ...

  2. 计算机硬件信息被修改怎么还原,修改bios硬件信息方法

    你们知道怎么BIOS的硬件信息怎么修改吗?下面是学习啦小编带来修改bios硬件信息方法的内容,欢迎阅读! 修改bios硬件信息方法: 按下主机箱上的开机键,在电脑出现第一屏幕信息时,屏幕会有进入CMO ...

  3. C# 读取电脑硬件信息

    我们有时遇到安装软件需要授权文件,就是利用电脑的硬件信息,来创建的授权文件的.加密和解密是很复杂的,可以独立一篇文章介绍一下,本文具体介绍C#获取电脑硬件信息,例如CPU信息,硬盘信息,RAM信息,主 ...

  4. linux 查看硬件 工具,linux下查看硬件信息方法

    想知道怎么查看电脑的硬件信息吗,下面是学习啦小编带来linux下查看硬件信息方法的内容,欢迎阅读! linux下查看硬件信息方法: 建议直接进主板的bios查看硬件信息 linux的话看具体什么版本了 ...

  5. 使用WMI编程获取主机硬件信息(CPU_ID,硬盘、主板、BIOS序列号,Mac地址)

    最近在公司实习,有个应用需要获取windows主机的一些硬件信息,在网上查阅了一些资料,大部分都是使用WMI编程来实现的. 因此小菜鸟自己也用WMI实现了一下,封装为函数GetUserInfo(),具 ...

  6. C#获取电脑硬件信息(CPU ID、主板ID、硬盘ID、BIOS编号

    C#获取电脑硬件信息(CPU ID.主板ID.硬盘ID.BIOS编号 http://www.cnblogs.com/liufei88866/archive/2010/05/11/1732671.htm ...

  7. c 获取计算机相关信息,C#编程获取各种电脑硬件信息的方法示例

    本文实例讲述了C#编程获取各种电脑硬件信息的方法.分享给大家供大家参考,具体如下: 获取CPU编号: ManagementClass mc = new ManagementClass("Wi ...

  8. 联想台式计算机的设备序列号,WMI获取硬件信息封装函数方法(联想台式机出厂编号 CPUID BIOS序列号 硬盘信息 显卡信息 MAC地址)...

    今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都是可以提取出来的,就自己把那些公共部分提出出来,以后如果要获取某部分的硬件信息就不用写一个一个的函数,比如获取MAC地址就写一个获取MAC地 ...

  9. html显示器对象属性,Web网站中利用JavaScript中ActiveXObject对象获取硬件信息(显示器数量、分辨率)从而进行单双屏跳转...

    前言:最近这两天工作上,要实现一个功能,在好友阿聪的帮助下,算是比较好的解决了这个需求. B/S的Web网站,需要实现点击按钮时,根据客户端连接的显示屏(监视器)数量进行,单双屏跳转显示新页面. 由于 ...

最新文章

  1. 28天打造专业红客(一)
  2. 反对网抄,没有规则可以创建目标install 靠谱解答
  3. 设计模式:访问者(Visitor)模式
  4. 简单了解Python网络爬虫
  5. java MySQL mq_蚂蚁社招Java岗面试分享(MySQL+RabbitMQ+Spring Boot)
  6. Springboot2 自定义异常处理
  7. arraylist扩容是创建新数组吗 java_Java ArrayList扩容问题实例详解
  8. python新手入门基础操作谨记这5点_Python大牛指点新手之:掌握这5点,可以快速从入门到进阶!...
  9. MiluGPS(迷路者GPS导航软件)
  10. java项目-第35期在线购书商城系统【毕业设计】
  11. 最有效的清理C盘/win10如何给系统盘瘦身
  12. iOS申请邓白氏总结
  13. rs.next()的理解
  14. blender 2.8的基本使用和使用形态键(Shape key)做帧动画
  15. LRC歌词制作LRC歌词制作
  16. [R语言] 生成随机数
  17. 快速上手云原生安全平台 NeuVector
  18. 基本函数依赖和候选键_[总结]关系数据库设计基础(函数依赖、无损连接性、保持函数依赖、范式、……)...
  19. 数据库单个插入操作转为批量插入
  20. 计算机30秒自动更换的桌面软件,电脑壁纸自动更换(SyncWall)

热门文章

  1. java文本域不可编辑_javascript:让表单 文本框 只读,不可编辑的方法
  2. 用python实现简单的汽车销售管理系统
  3. 有趣php小程序,最近发现的 5 个微信小程序,有趣又实用!
  4. java语言程序设计培训_JAVA语言程序设计Z
  5. Linux 中文显示
  6. OFBIz gradle构建与运行踩坑
  7. Oracle EBS Interface/API(31) -PR最终关闭API
  8. Python之面向对象(封装、继承、多态)
  9. Android Build类获取系统信息
  10. 高德地图简单点位+轨迹+描述