无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站广告联系 微信:wuyouceo QQ:184822951
查看: 2834|回复: 6
打印 上一主题 下一主题

int13 handler 数据结构微调及相关代码更改事宜

[复制链接]
跳转到指定楼层
1#
发表于 2015-9-5 22:52:49 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
在 int13 handler 的偏移 0x10 处,有 12 个保留字节。其中前 4 个字节现在准备用于存放扩展内存 int13 空间的地址(以 512-byte sector 为单位,不是以字节为单位)。其余 8 个字节仍旧处于保留状态。另外,偏移 0x04 处的“G4DS”签名中的一个或两个字节,有可能被用于存放 ahci 硬盘驱动的 bios 盘号(DL)。偏移 0x08 处的两字节的 Version Number 准备废弃,将来在必要时可以用作其他目的。

int15 处理程序代码已经进行了相应的修改,能够识别出扩展内存的 int13 空间,并加以保护。

map 命令也正在进行修改,让它能够识别出扩展内存上的 int13 空间。

以上修改是在 0.4.5c 上进行的。

7#
 楼主| 发表于 2015-9-15 21:01:48 | 只看该作者
在改造的过程中,发现了 chenall 的进程管理代码中,有个以前解决不了的问题:

psp = (char *)grub_malloc(prog_len * 2 + psp_len);

在这个代码中,chenall 用加倍分配内存的方式,来解决进程长度超过文件长度的问题。

这显然不是根本性的解决办法,只是权宜之计。严格来说,这种方法是错误的(应该说是个已知的 bug)。不过,我们当时是没办法解决的,因为我们无法获得进程长度。用户时常报告 FAT 或者别的外部命令运行时出现莫名其妙的错误,我怀疑与这个 bug 有关。

现在我们有办法得到进程长度了,因此,上述进程处理代码应该加以完善和解决了。

新的进程处理代码要求新的可执行文件格式,不再支持旧的可执行文件格式。这是因为旧的可执行文件格式不含进程长度字段,无法确定进程长度。

回复

使用道具 举报

6#
 楼主| 发表于 2015-9-14 11:21:29 | 只看该作者
在改造的过程中发现,原来的 PSP 进程数据结构设计有个令人难受的弊端。

在开发的早期,我只是学习 DOS 的做法,弄个 PSP 在进程空间的最开头。DOS 的 PSP 占用 256 字节,而我们的 PSP 长度是可变的。

然而,PSP 处于进程空间的最开头,其坏处之一就是破坏了对齐性。具体来说,我遇到这样的问题:

ahci 程序需要一些按照 4K 对齐的内存。这需要在程序开始运行之后动态分配。

假定进程的 PSP 被分配为 4K 对齐,那么,既然保证动态分配的内存也是 4K 对齐,那就无法保证 main 的地址是 4K 对齐(除非修改内核的进程管理代码,让 PSP 的长度总是 4K 的倍数,这样是很大的浪费)。

这样,如果要把 ahci 程序自身挪到扩展内存顶端,就需要连同 PSP 一起挪动(否则就不是从 4K 对齐的边界处开始挪动)。而且为了做成 int13 的处理程序,我们在 PSP 之前还需要增加其他一些结构,比如说,记录 int13 处理程序的长度,记录常规内存 int13 处理程序的地址,还要有保护模式的中断描述符表(它占用 2K),等等。这些附加的结构,设计为 8K,这 8K 之后,紧接着就是 PSP。而 PSP 之后,紧接着就是 main 函数。

然而问题出来了:8K 的 int13 信息空间与 main 函数之间,隔着个可变长度的 PSP。这就让 8K 的 int13 空间与 main 的代码不能直接访问(相对位置的差值不是常数,而是变化的)。虽然 PSP 的长度是可以确定的,但这是通过变量来计算的。这个 PSP 夹在中间,带来了很多计算方面的负担。这是个瓶颈,如果没有这个可变长度的 PSP,我们的计算要简单得多,程序也容易看懂。有了这个 PSP,每次互访,地址都要经过转换、计算,程序太复杂了,给后来的开发者造成了阅读代码的痛苦。

为此我考虑解决的办法。进程开头直接放置 main 代码,而把 PSP 挪到进程尾部。

进程的长度可以通过 _end 变量来确定。gcc 用 end 或 _end 来表示 __bss_end。这样,我找到了一个办法,让进程的长度能够记录在 ahci 程序的结尾附近。内核的进程管理代码可以读出 ahci 进程所需要的长度,并在 _end 处开始放置 PSP。如此一来,问题就解决了。

回复

使用道具 举报

5#
 楼主| 发表于 2015-9-11 21:31:57 | 只看该作者
保留空间数据结构初步设计。

偏移 0x0000: 保留(暂不使用)
偏移 0x0218: 保留空间的分割区个数。
偏移 0x021C: 保留空间的总量(以扇区数为单位)。
偏移 0x0220: 保留空间第一分割区的长度(以扇区为单位)。
偏移 0x0224: 保留空间第二分割区的长度(以扇区为单位)。
偏移 0x0228: 保留空间第三分割区的长度(以扇区为单位)。
偏移 0x022C: 保留空间第四分割区的长度(以扇区为单位)。
偏移 0x0230: 保留空间第五分割区的长度(以扇区为单位)。
偏移 0x0234: 保留空间第六分割区的长度(以扇区为单位)。
偏移 0x0238: 保留空间第七分割区的长度(以扇区为单位)。
偏移 0x023C: 保留空间第八分割区的长度(以扇区为单位)。

偏移 0x0400: 常规内存 int13_handler 线性基地址。
偏移 0x0404: int13_realmode_int 的线性基地址。
偏移 0x0408: int13_interrupt_number 的线性基地址。

偏移 0x0800: IDT
偏移 0x1000: 保留 4K(暂不使用)
偏移 0x2000: psp

回复

使用道具 举报

4#
 楼主| 发表于 2015-9-7 13:10:26 | 只看该作者
好了,现在,int13 在扩展内存上的空间是已经被保护了的。

我们可以加大这个空间的容量,让它可以用于其他目的,比如用于存放字库字模。

初步计划,这个空间的最低端,用于 int13 的处理代码。2M 已经不少了。

前面说过,这个空间的起始地址记录在常规内存的 int13 空间的偏移 0x10 处。而它的长度则记录在另外一个变量中(刚才也说了,初步定为 2M)。紧接着在它之上,是自由内存,由用户任意使用。这个内存如果太小,恐怕不够用。所以,我想一开始就弄大点,保留 16M 空间吧。内核也可以任意读写这个空间。就是说,这个空间的数据,会被别的使用者改变,只能临时使用。内核程序无需经过 kmalloc 就可以使用这个空间,所以,这个空间有它的好处。紧接着往上,是 kmalloc 内存,也为它保留 16M。再紧接着往上,是字库内存,为其保留 32M 空间。如此一来,整个保留空间的总量是 66M。概括如下:

保留空间量 = int13 以及将来的系统所使用的空间(2M 或更多,是可变的,记录在内核变量中)
           + 任意读写空间(16M 或更多,是可变的,记录在内核变量中)
           + kmalloc空间(16M 或更多,是可变的,记录在内核变量中)
           + 字库字模(32M 或更多,是可变的,记录在内核变量中)

系统启动之后,就尽快确定保留空间的基地址,并记录在 int13 空间的偏移 0x10 处。整个保留空间的量在本次系统启动之后一般是不变的。动态改变大小的可能性也是有的,只不过需要小心处理相关的问题。

系统退出时,要卸载其中一些不必要的内存占用,再用 map --rehook 等方式让已经 map 了的内存盘使用这些空间。

回复

使用道具 举报

3#
 楼主| 发表于 2015-9-6 18:23:09 | 只看该作者
今天忽然有个想法,觉得目前 32M 的系统保留内存,也已经够用了。至于说字体字模占用内存的事情,可以像 chenall 提议的,用外部命令来实现。至于说外部命令究竟如何实现,可以参考我正在做的工作,即,用外部命令来实现 ahci 驱动。

外部命令实现 ahci 驱动的大致步骤如下:

外部命令 ahci 执行后,先把自己移动到扩展内存顶部,把地址记录在 int13 处理程序的一个变量中,使得它被 int15 保护。

然后,设置好常规内存里面的 int13 处理程序,让它能够使用位于扩展内存的 int13 代码。

字体文件可以考虑放在某个内存盘中。内存盘的基地址记录在某个变量中。同时,修改 grub4dos 内核,使其可以根据这个基地址变量的指示的来使用字模。

回复

使用道具 举报

2#
发表于 2015-9-6 12:31:43 | 只看该作者
围观,表示完全看不懂...
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2024-9-22 06:59

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表