给i386写驱动 -1

几个学习链接:
https://www.cnblogs.com/LexMoon/p/How_to_Make_a_Computer_Operating_System.html
https://github.com/SamyPesse/How-to-Make-a-Computer-Operating-System
这两个连接有点复杂,vagrant很难用的样子,所以放弃了
https://www.cnblogs.com/LexMoon/p/antz01.html
这个里面有nasm什么的工具,看不懂,所以放弃了

以上几个大神博客里写了引导过程,我尽量理解一下,大神自问自答了挺多,方便我这种菜鸡理解。
第一个大神:

什么是x86架构?

x86是指一组基于Intel 8086 CPU的向后兼容指令集架构。

引导是如何工作的?

当一台基于x86的计算机被启动时,它会经历一段很复杂的路程,以到达将控制权转移到内核“主”例程(“kmain()”)的阶段。
BIOS引导序列为:RAM检测->硬件检测/初始化->引导序列。
对我们来说最重要的步骤是“引导序列”,此时BIOS完成了初始化,并试图将控制转移到引导加载程序的下一个阶段。
在“引导顺序”期间,BIOS将尝试确定一个“引导设备”(例如软盘、硬盘、CD、USB闪存设备或网络)。我们的操作系统最初将从硬盘引导(但是将来可以从CD或USB闪存设备引导它)。
如果引导扇区在偏移量511和512处分别包含有效的签名字节' 0x55 '和' 0xAA '(称为主引导记录的魔法字节,也称为MBR),则认为设备是可引导的。
此签名(以二进制)表示为0b1010101001010101。交替位模式被认为是对某些故障(驱动或控制器)的保护。
如果该模式被打乱或0x00,则认为该设备不可引导。
BIOS通过将每个设备的引导扇区中的前512字节加载到物理内存中来物理搜索引导设备,加载到从地址“0x7C00”(低于32 KiB标记的1 KiB)开始的那么一段内存上。当检测到有效的签名字节时,BIOS将控制传输到“0x7C00”内存地址(通过跳转指令),以便执行引导扇区代码。
在整个过程中,CPU一直以16位实模式运行,这是x86 CPU为了保持向后兼容性的默认状态。要在内核中执行32位指令,需要一个引导加载程序将CPU切换到保护模式。
挺这意思都是Intel在做8086处理器的时候,和BIOS商量好的,这BIOS可能就是英特尔出的,像是个硬件加载器的感觉

什么是GRUB?

GNU GRUB (GNU GRand Unified Bootloader的简称)是GNU项目中的一个引导加载程序包。
GRUB是自由软件基金会(Free Software Foundation)的多引导规范的参考实现,该规范为用户提供了从安装在计算机上的多个操作系统中引导一个操作系统或选择特定操作系统分区上可用的特定内核配置的选项。
简单来说,GRUB是机器(引导加载程序)启动的第一件事,它将简化存储在硬盘上的内核的加载

我们为什么要使用GRUB?

  • GRUB非常容易使用
  • 使加载32位内核非常简单,不需要16位代码
  • 多引导与Linux, Windows和其他
  • 便于在内存中加载外部模块

如何使用GRUB?

GRUB使用多引导规范,可执行二进制文件应该是32位的,并且必须包含一个特殊的头(多引导头),头8192个字节。
我们的内核将是ELF可执行文件(“可执行和可链接格式”,大多数UNIX系统中可执行文件的通用标准文件格式)。
我们内核的第一个引导序列是使用汇编编写的。
我们使用一个链接器文件来定义我们的可执行结构。
这个引导过程还初始化了一些c++运行时,将在下一章中进行描述。
Multiboot头结构:

struct multiboot_info {
    u32 flags;
    u32 low_mem;
    u32 high_mem;
    u32 boot_device;
    u32 cmdline;
    u32 mods_count;
    u32 mods_addr;
    struct {
        u32 num;
        u32 size;
        u32 addr;
        u32 shndx;
    } elf_sec;
    unsigned long mmap_length;
    unsigned long mmap_addr;
    unsigned long drives_length;
    unsigned long drives_addr;
    unsigned long config_table;
    unsigned long boot_loader_name;
    unsigned long apm_table;
    unsigned long vbe_control_info;
    unsigned long vbe_mode_info;
    unsigned long vbe_mode;
    unsigned long vbe_interface_seg;
    unsigned long vbe_interface_off;
    unsigned long vbe_interface_len;
};

您可以使用命令 mbchk kernel.elf来根据多引导标准验证kernel.elf文件。您还可以使用nm -n kernel.elf验证elf二进制文件中不同对象的偏移量。

这两个指令好像挺犀利啊

为内核和grub创建一个磁盘映像

第一步是使用qemu-img创建硬盘映像(c.img):

qemu-img create c.img 2M

我们现在需要使用fdisk来分区磁盘:

fdisk ./c.img
# Switch to Expert commands 切换到专家命令
> x
# Change number of cylinders (1-1048576) 修改柱面数量(1-1048576)
> c
> 4
# Change number of heads (1-256, default 16) 改变磁头数量(1-256,默认16)
> h
> 16
# Change number of sectors/track (1-63, default 63) 更改磁道数目(1-63,默认63)
> s
> 63
# Return to main menu 返回主菜单
> r
> 真牛逼,专家模式还能定义硬盘参数
# Add a new partition 添加一个新分区
> n
# Choose primary partition 选择主分区
> p
# Choose partition number 选择分区号
> 1
# Choose first sector (1-4, default 1) 选择第一个扇区(1-4,默认1)
> 1
# Choose last sector, +cylinders or +size{K,M,G} (1-4, default 4) 选择最后一个扇区,+柱面或+大小{K,M,G}(1-4,默认4)
> 4
# Toggle bootable flag 切换启动的标志
> a
# Choose first partition for bootable flag 为可引导标志选择第一个分区
> 1
# Write table to disk and exit 将表写到磁盘并退出
> w

现在我们需要使用losetup命令将创建的分区附加到loop设备上。这允许像块设备一样访问文件。
分区的偏移量作为参数传递并使用:offset= start_扇区 bytes_by_扇区*计算。
使用 fdisk -l -u c.img, 你将得到: 63 * 512 = 32256.

losetup -o 32256 /dev/loop1 ./c.img

我们使用以下命令在这个新设备上创建EXT2文件系统:

mke2fs /dev/loop1

我们复制我们的文件在一个挂载磁盘:

mount  /dev/loop1 /mnt/
cp -R bootdisk/* /mnt/
umount /mnt/

在磁盘上安装GRUB:

grub --device-map=/dev/null << EOF
device (hd0) ./c.img
geometry (hd0) 4 16 63
root (hd0,0)
setup (hd0)
quit
EOF

最后我们分离驱动循环:

losetup -d /dev/loop1

第二个大神:

1.关于Boot Sector

引导扇区(Boot Sector) 通常指设备的第一个扇区,用于加载并转让处理器控制权给操作系统。

1.1 主引导扇区

硬盘的0柱面、0磁头、1扇区称为[主引导扇区]
该记录占用512个字节,它用于硬盘启动时将系统控制权转给用户指定的、在分区表中登记了某个[操作系统]分区。

MBR的内容是在硬盘分区时由分区软件写入该扇区的,MBR不属于任何一个操作系统,不随操作系统的不同而不同,即使不同,MBR也不会夹带操作系统的性质,具有公共引导的特性。
但安装某些多重引导功能的软件或LINUX的LILO时有可能改写它,它先于所有的操作系统被调入内存并发挥作用,然后才将控制权交给活动主分区内的操作系统。

1.2 MBR成员

1.主引导程序代码,占446字节

2. 磁盘签名
    3.硬盘分区表DPT,占64字节
    4.主引导扇区结束标志55AAH
硬盘的主引导程序代码是从偏移0000H开始到偏移01BDH结束的446字节;
主引导程序代码包括一小段执行代码。
启动PC 机时,系统首先对硬件设备进行测试,成功后进入自举程序INT 19H;
然后读系统磁盘0[柱面]、0[磁头]、1[扇区]的主引导扇区MBR的内容到内存以指定单元0:7C00 首地址开始的区域,并执行MBR程序段。

这里要学习一下硬盘知识了

硬盘柱面是硬盘的一个物理结构部分。
硬盘的主体部分是由铝合金材料制成的涂以磁性介质的数个圆形盘片,每个盘片的两面涂有磁涂层,用来记录数据。
硬盘的柱面,牵扯到硬盘的[物理结构]:
硬盘的主体部分是由铝合金材料制成的涂以磁性介质的数个圆形[盘片],串在一个高速旋转的轴上,不同容量硬盘的盘片数不等,每个盘片的两面涂有磁涂层,用来记录数据。
盘片被分成许多扇形的区域,每个区域就叫一个[扇区],每个扇区可存储128×2的N次方(N=0.1.2.3)[字节]信息。
以盘片中心为圆心;用不同的半径;划分出不同的很窄的圆环形区域,称为[磁道]。
上下一串盘片中,相同半径的磁道所组成的一个圆柱型的环壁,就称为柱面。
也就是说,一个盘片上的一个扇区,最少能存256Byte;最多,可以到512,1024,2048Byte?那我平时总能听到的2096是咋回事儿?
还有就是这个柱面,我现在都是单盘多少T,那也就是只有一个柱面咯。

磁头是硬盘中对盘片进行读写工作的工具,是硬盘中最精密的部位之一。
磁头是用线圈缠绕在磁芯上制成的。
硬盘在工作时,磁头通过感应旋转的盘片上磁场的变化来读取数据;通过改变盘片上的磁场来写入数据。
为避免磁头和盘片的磨损,在工作状态时,磁头悬浮在高速转动的盘片上方,而不与盘片直接接触;
只有在电源关闭之后,磁头会自动回到在盘片上的固定位置,称为[着陆区],此处盘片并不存储数据,是盘片的起始位置)。

[磁盘]上的磁道是一组记录密度不同的同心圆。
[磁表面存储器]是在不同形状(如盘状、带状等)的载体上,涂有磁性材料层,工作时,靠载磁体高速运动,由磁头在磁层上进行读写操作,信息被记录在磁层上,这些信息的轨迹就是磁道。
磁盘的磁道是一个个同心圆,见右图,磁带的磁道是沿磁带长度方向的直线,这些磁道用肉眼是根本看不到的,因为它们仅是盘面上以特殊方式磁化了的一些磁化区,磁盘上的信息便是沿著这样的轨道存放的。
相邻磁道之间并不是紧挨着的,这是因为磁化单元相隔太近时磁性会产生相互影响,同时也为磁头的读写带来困难。
一张老式1.44MB的3.5英寸软盘,一面有80个磁道,而硬盘上的[磁道密度]则远远大于此值,通常一面有成千上万个磁道。
硬盘的物理结构一般由磁头与盘片、电动机、主控芯片与排线等部件组成
当主电动机带动盘片旋转时,副电动机带动一组(磁头)到相对应的盘片上并确定读取正面还是反面的碟面,
磁头悬浮在碟面上画出一个与盘片同心的圆形轨道(磁轨或称柱面),
这时由磁头的磁感线圈感应碟面上的磁性与使用硬盘厂商指定的读取时间或数据间隔定位扇区,从而得到该扇区的数据内容;当磁盘旋转时,磁头若保持在一个位置上,则每个磁头都会在磁盘表面划出一个圆形轨迹,这些圆形轨迹就叫做磁道(Track)。
在有多个盘片构成的盘组中,由不同盘片的面,但处于同一半径圆的多个磁道组成的一个圆柱面(Cylinder)。
磁盘上的每个磁道被等分为若干个弧段,这些弧段便是硬盘的扇区(Sector)。硬盘的第一个扇区,叫做引导扇区。
真尼玛涨知识

[磁盘]的每一面被分为很多条[磁道],即表面上的一些[同心]圆,
越接近中心,圆就越小。而每一个[磁道]又按512个[字节]为单位划分为等分,叫做扇区,
刚才上面还说,一个盘片上的一个扇区,最少能存256Byte;最多,可以到512,1024,2048Byte,怎么这里就变成固定512了。好吧,以这里为准。
在一些[硬盘]的[参数列表]上你可以看到描述每个磁道的[扇区数]的参数,它通常用一个范围标识,例如373~746,
这表示,最外圈的磁道有746个扇区,而最里面的磁道有373个扇区,因此可以算出来,磁道的容量分别是从186.5KB到373KB(190976B--381952B)
[磁盘驱动器]在向磁盘读取和写入数据时,要以扇区为单位。
在磁盘上,[DOS]操作系统是以“[簇]”为单位为文件分配磁盘空间的。
[硬盘]的簇通常为多个扇区,与[磁盘]的种类、DOS 版本及[硬盘分区]的大小有关。
每个簇只能由一个文件占用,即使这个文件中有几个[字节],决不允许两个以上的文件共用一个簇,否则会造成数据的混乱。
这种以簇为最小分配单位的机制,使[硬盘]对数据的管理变得相对容易,但也造成了[磁盘]空间的浪费,尤其是小文件数目较多的情况下,一个上千兆的大硬盘,其浪费的磁盘空间可达上百兆[字节]。
为了对扇区进行查找和管理,需要对扇区进行编号,扇区的编号从0磁道开始,起始扇区为1扇区,其后为2扇区、3扇区……,
0磁道的扇区编号结束后,1磁道的起始扇区累计编号,直到最后一个磁道的最后一个扇区(n扇区)。
例如,某个硬盘有1024个磁道,每个磁道划分为63个扇区,则0磁道的扇区号为1~63,1磁道的起始扇区号为64最后一个磁道的最后一个扇区号为64512。
硬盘在进行扇区编号时与软盘有一些区别,在软盘的一个磁道中,扇区号一次编排,即1、2、3……n扇区。
由于硬盘的转速较高,磁头在完成某个扇区数据的读写后,必须将数据传输到微机,这需要一个时间,
但是这时硬盘在继续高速旋转,当数据传输完成后,磁头读写第二个扇区时,磁盘已经旋转到了另外一个扇区。
因此在早期硬盘中,扇区号是按照某个间隔系数跳跃编排的。
在[硬盘]中无法被正常访问或不能被正确读写的扇区都称为Badsector。
一个扇区能存储512[Bytes]的数据,如果在某个扇区中有任何一个[字节]不能被正确读写,则这个扇区为Badsector。
除了存储512Bytes外,硬盘每个扇区还有数十个Bytes信息,包括标识(ID)、校验值和其它信息。
这些信息任何一个[字节]出错都会导致该扇区变“Bad”。
例如,在[低级格式化]的过程中每个扇区都分配有一个编号,写在ID中。
如果ID部分出错就会导致这个扇区无法被访问到,则这个扇区属于Badsector。
有一些Badsector能够通过[低级格式化]重写这些信息来纠正。

下面的clust也就是簇的概念,是文件系统的概念
数据存储在硬盘的时候都是以簇为单位,所以无论文件大小是多少,除非正好是簇大小的倍数,否则文件所占用的最后一个簇或多或少都会产生一些剩余的空间,且这些空间又不能给其它文件使用,
即使这个文件只有0字节,也不允许两个文件或两个以上的文件共用一个簇,不然会造成数据混乱。
微软操作系统(DOS、WINDOWS等)中磁盘文件存储管理的最小单位叫做“簇”
一个文件通常存放在一个或多个簇里,但至少要单独占据一个“簇”。 也就是说两个文件不能存放在同一个簇中。
簇(CLUST)的本意就是“一群”、“一组”,即一组扇区的意思。
因为[扇区]的单位太小,因此把它捆在一起,组成一个更大的单位更方便进行灵活管理。
簇的大小通常是可以变化的,是由操作系统在所谓“(高级)格式化”时规定的,因此管理也更加灵活。

通俗地讲文件就好[比是]一个家庭,数据就是人,即家庭成员;
所谓簇就是一些单元套房;
[扇区]是组成这些单元套房的一个个大小相等的房间。
一个家庭可能住在一套或多套单元房子里,但一套房子不能同时住进两个家庭的成员。
[文件系统]是操作系统与驱动器之间的接口,当操作系统请求从硬盘里读取一个文件时,会请求相应的文件系统(FAT 16/[FAT32]/[NTFS]打开文件。
[扇区]是磁盘最小的物理存储单元,但由于操作系统无法对数目众多的扇区进行[寻址],所以操作系统就将相邻的扇区组合在一起,形成一个簇,然后再对簇进行管理。
每个簇可以包括2、4、8、16、32或64个[扇区]。显然,簇是操作系统所使用的逻辑概念,而非磁盘的物理特性。

那么对应的簇的大小就是1024,2048,4096,8192,16385,65536咯,其实我还看到2M的了呢。
为了更好地管理磁盘空间和更高效地从硬盘读取数据,操作系统规定一个簇中只能放置一个文件的内容,因此文件所占用的空间,只能是簇的整数倍;
如果文件实际大小小于一簇,它也要占一簇的空间。
如果文件实际大小大于一簇,根据逻辑推算,那么该文件就要占两个簇的空间。
所以,一般情况下文件所占空间要略大于文件的实际大小,只有在少数情况下,即文件的实际大小恰好是簇的整数倍时,文件的实际大小才会与所占空间完全一致。

现在可以开始学习第二个大神的内容了

1.3MBR功能

1.扫描分区表查找[活动分区]
    2.寻找活动分区的起始扇区;
    3.将活动分区的引导扇区读到内存;
    4.执行引导扇区的运行代码。
      如果主引导代码未完成这些功能,系统显示下列错误信息
      Invalid partition table
      Error loading operating system
      Missing operating system
MBR是BIOS接力的第一棒,在他之后,会由分区引导扇区DBR接力,至于为什么不直接给DBR。
那是因为BIOS大小有限,无法完成所有操作,在给DBR之前会通过MBR完成。
目前只需要了解MBR,至于DBR会在之后进行解释。

2.Boot Sector实现代码

在BIOS自检等一系列工作完成后,要开始引导了。
计算机会将硬盘0面0道1扇区512字节加载到07c00h(0000::7c00)处。
1)为什么是0面0道1扇区?
这个可以理解为是规定,当Bios工作完成后会去将硬盘0面0道1扇区512字节进行加载。
但是真实情况是根据“魔数”来确定的,魔数就是有特殊意义的数,更大作用是用来做标记,比如MBR就是在512个字节的最后两个字节填入 0x55 ,0xaa来进行标记的。
放在第一个扇区是因为0面0道1扇区是磁盘最开始的地方,一开始检验出有 0x55 ,0xaa就直接开始加载。
2)为什么是07c00h?
这个也可以当作是规定,在IBM文档中没有具体说明07c00h是为什么,
但是在世界上第一台个人计算机诞生时,07c00h就是在它当中初次诞生的,
那时的DOS最多也就是32K,为了实现MBR中的栈需要512B,
为了满足需求取最大为1K,也就是32K-1K,就是07c00h了。

原来这个地址是IBM规定的呀

你可能感兴趣的:(给i386写驱动 -1)