• 老王
    2021-06-07
    有了前面基础实验很快就做通了,只是实验步骤课程没有说 1.下载最新源码 git clone https://gitee.com/lmos/cosmos.git 2 进入课程的目录 cd cosmos/lesson13/Cosmos 3 编译 make all 这个过程中可能会报告错误 ../hal/x86/kernel.asm:6: fatal: unable to open include file `kernel.inc' krnlbuidrule.mk:14: recipe for target 'kernel.o' failed make[2]: *** [kernel.o] Error 1 Makefile.x86:28: recipe for target 'all' failed make[1]: *** [all] Error 2 Makefile:59: recipe for target 'all' failed make: *** [all] Error 2 警告不管 解决错误即可 使用 find -name "kernel.inc" 搜索头文件的位置 ./include/halinc/kernel.inc 把这个头文件拷贝到和kernel.asm相同的目录。或者是更改../hal/x86/kernel.asm 第6行 改为%include "../include/halinc/kernel.inc" 再次make 可以正常编译 4.生成内核镜像文件 make cplmildr (这一步会拷贝 initldrimh.bin initldrkrl.bin initldrsve.bin 到源码顶层目录的release下 ) make cprelease (这一步会拷贝 Cosmos.bin 到源码顶层目录的release下 ) make KIMG (这一步会调用lmoskrlimg 把initldrimh.bin initldrkrl.bin initldrsve.bin Cosmos.bin logo.bmp background.bmp font.fnt按一定的格式打包成Cosmos.eki镜像文件 ) 5.拷贝Cosmos.eki镜像文件到虚拟磁盘 源码目录已经创建了磁盘文件hd.img(如果没有这个文件可以按照前面的课程自己创建) sudo mount -o loop ./hd.img ./hdisk/ (挂载虚拟磁盘到hidsk目录,hd.img hidsk目录已经存在) sudo cp release/Cosmos.eki hdisk/boot (拷贝编译好的镜像Cosmos.eki 到虚拟磁盘中) sudo umount hdisk (卸载挂载目录/或者是目录和磁盘中的内容) VBoxManage convertfromraw ./hd.img --format VDI ./hd.vdi (把hd.img转为hd.vdi格式,因为课程使用的虚拟机是VirtualBox) 6.参考前面课程使用hd.vdi启动系统 总结: 要想搞清楚整个程序的流程,除了分析代码本身,还需要深入分析Makefile和各个链接脚本
    展开

    编辑回复: 感谢老铁的分享,特别赞。

    共 9 条评论
    40
  • neohope
    2021-06-08
    稍微整理了一下: 一、HAL层调用链 hal_start() A、先去处理HAL层的初始化 ->init_hal() ->->init_halplaltform()初始化平台 ->->->init_machbstart() 主要是把二级引导器建立的机器信息结构,复制到了hal层一份给内核使用,同时也为释放二级引导器占用内存做好准备。 其做法就是拷贝了一份mbsp到kmbsp,其中用到了虚拟地址转换hyadr_to_viradr ->->->init_bdvideo() 初始化图形机构 初始化BGA显卡 或 VBE图形显卡信息【函数指针的使用】 清空屏幕 找到"background.bmp",并显示背景图片 ->->->->hal_dspversion() 输出版本号等信息【vsprintfk】 其中,用ret_charsinfo根据字体文件获取字符像素信息 ->->move_img2maxpadr() 将移动initldrsve.bin到最大地址 ->->init_halmm()初始化内存 ->->->init_phymmarge 申请phymmarge_t内存 根据 e820map_t 结构数组,复制数据到phymmarge_t 结构数组 按内存开始地址进行排序 ->->init_halintupt();初始化中断 ->->->init_descriptor();初始化GDT描述符x64_gdt ->->->init_idt_descriptor();初始化IDT描述符x64_idt,绑定了中断编号及中断处理函数 ->->->init_intfltdsc();初始化中断异常表machintflt,拷贝了中断相关信息 ->->->init_i8259();初始化8529芯片中断 ->->->i8259_enabled_line(0);好像是取消mask,开启中断请求 最后,跳转去处理内核初始化 ->init_krl() 二、中断调用链,以硬件中断为例 A、kernel.inc中,通过宏定义,进行了中断定义。以硬件中断为例,可以在kernel.inc中看到: 宏为HARWINT,硬件中断分发器函数为hal_hwint_allocator %macro HARWINT 1 保存现场...... mov rdi, %1 mov rsi,rsp call hal_hwint_allocator 恢复现场...... %endmacro B、而在kernel.asm中,定义了各种硬件中断编号,比如hxi_hwint00,作为中断处理入口 ALIGN 16 hxi_hwint00: HARWINT (INT_VECTOR_IRQ0+0) C、有硬件中断时,会先到达中断处理入口,然后调用到硬件中断分发器函数hal_hwint_allocator 第一个参数为中断编号,在rdi 第二个参数为中断发生时的栈指针,在rsi 然后调用异常处理函数hal_do_hwint D、hal_do_hwint 加锁 调用中断回调函数hal_run_intflthandle 释放锁 E、hal_run_intflthandle 先获取中断异常表machintflt 然后调用i_serlist 链表上所有挂载intserdsc_t 结构中的中断处理的回调函数,是否处理由函数自己判断 F、中断处理完毕 G、异常处理类似,只是触发源头不太一样而已
    展开

    作者回复: 老哥 6666

    共 2 条评论
    18
  • pedro
    2021-06-07
    [ hal_start ] --> [ init_hal ] --> [ init_krl ] [ init_hal ] --> [ init_halplaltform ] --> [ move_img2maxpadr ] --> [ init_halmm ] --> [ init_halintupt ] [ init_krl ] --> [ die ] [ init_halplaltform ] --> [ init_machbstart ] --> [ init_bdvideo ] [ init_halmm ] --> [ init_phymmarge ] [ init_halintupt ] --> [ init_descriptor ] --> [ init_idt_descriptor ] --> [ init_intfltdsc ] --> [ init_i8259 ] --> [ i8259_enabled_line ] 如果有 graph-easy 的同学,直接 CV,然后: ```sh graph-easy calltree.txt ```

    作者回复: 铁汁牛皮

    共 4 条评论
    14
  • LunaElf
    2021-10-19
    Cosmos hal 层函数调用关系: 1. `hal_start()` 1. `init_hal()` 1. `init_halplatform()` 1. `init_machbstart()` 1. `machbstart_t_init()` 2. `init_bdvideo()` 2. `init_halmm()` 1. `init_phymmarge()` 1. `initpmrge_core()` 3. `init_halintupt()` 1. `init_idt_descriptor()` 1. `set_idt_desc()` 2. `init_intfltdsc()` 3. `init_i8259()` 2. `init_krl()` 1. `hal_fault_allocator()` 1. `hal_do_hwint()` 1. `hal_run_intflthandle()` 1. `hal_hwint_allocator()` 1. `hal_do_hwint()` 1. `hal_run_intflthandle()`

    作者回复: 66666

    
    4
  • 卢承灏
    2021-09-07
    有一个问题,回过头来二刷的时候没想明白,如果中断传递的只是一个中断号,然后中断号是进行共用的,那在hal_run_intflthandle 中的list_for_each 中,每个设备注册的handler方法,怎么判断自己需不需要执行呢? handler传入的s->device 也是从循环中的每一个intserdsc_t取出,和最开始的中断号看不出中什么关联。还希望大神们解答

    作者回复: 中断共享 需要设备驱动程序自己处理

    共 2 条评论
    4
  • 云师兄
    2021-06-09
    太硬了啊,有点磕牙,不过再咬两口试试😬

    编辑回复: 哈哈哈,舌尖上的操作系统,老铁加油!

    
    4
  • 吴建平
    2021-07-01
    代码走查出一个安全问题,下面这个函数里,如果for里一个满足条件的都没找到,那么后面校验的时候 retemp->saddr 就空指针了。 e820map_t *ret_kmaxmpadrcmpsz_e820map(machbstart_t *mbsp, u64_t mappadr, u64_t cpsz) { if (NULL == mbsp) { return NULL; } u64_t enr = mbsp->mb_e820nr; e820map_t *emp = (e820map_t *)phyadr_to_viradr((adr_t)mbsp->mb_e820padr); e820map_t *retemp = NULL; u64_t maxadr = emp[0].saddr; for (u64_t i = 0; i < enr; i++) { if (emp[i].type == RAM_USABLE) { if (emp[i].saddr >= maxadr && //内存区首地址大于已知最大区域起始地址(初始化位第一个区首地址 (mappadr > (emp[i].saddr + emp[i].lsize)) && //内存区尾地址小于内存映射最大地址 (emp[i].lsize >= cpsz)) //内存区大小大于镜像文件大小 { maxadr = emp[i].saddr; //已知最大区域起始地址 retemp = &emp[i]; //更新最后满足条件内存区域 } } } if ((mappadr > (retemp->saddr + retemp->lsize)) && (retemp->lsize >= cpsz)) //校验,但除非一个都不满足条件 { return retemp; } return NULL; }
    展开

    作者回复: 对的 厉害了 找出了BUG

    
    2
  • 然
    2021-06-07
    很好奇move_img2maxpadr(&kmachbsp);这个函数 功能:move_img2maxpadr(&kmachbsp);这个函数是把镜像文件搬到最大的物理地址处。 作用:我感觉是因为镜像文件是加载在0x4000000处,而空闲地址是从内核文件加载处开始计算的(0x2000000+内核大小),随着内存的分配,空闲地址不断向上增长,迟早会覆盖镜像文件,所以提前把镜像文件搬走了。

    作者回复: 对,你理解的很正确

    
    2
  • Victor
    2021-06-07
    在ubuntu 18.04环境下make时报错: root@ubuntu1804:~/LMOS/cosmos/lesson13/Cosmos# make all Initldr:清理全部已构建文件... ^_^ *********正在开始编译构建系统************* AS -[M] 正在构建... ../ldrkrl/imginithead.asm CC -[M] 正在构建... ../ldrkrl/inithead.c CC -[M] 正在构建... ../ldrkrl/vgastr.c AS -[M] 正在构建... ../ldrkrl/ldrkrl32.asm CC -[M] 正在构建... ../ldrkrl/ldrkrlentry.c CC -[M] 正在构建... ../ldrkrl/fs.c CC -[M] 正在构建... ../ldrkrl/chkcpmm.c CC -[M] 正在构建... ../ldrkrl/graph.c CC -[M] 正在构建... ../ldrkrl/bstartparm.c AS -[M] 正在构建... ../ldrkrl/realintsve.asm OBJCOPY -[M] 正在构建... initldrimh.bin OBJCOPY -[M] 正在构建... initldrkrl.bin OBJCOPY -[M] 正在构建... initldrsve.bin 恭喜我,Initldr编译构建完成! ^_^ ../hal/x86/kernel.asm:6: fatal: unable to open include file `kernel.inc' krnlbuidrule.mk:14: recipe for target 'kernel.o' failed make[2]: *** [kernel.o] Error 1 Makefile.x86:28: recipe for target 'all' failed make[1]: *** [all] Error 2 Makefile:59: recipe for target 'all' failed make: *** [all] Error 2
    展开

    作者回复: 是不是下载 的完整代码

    共 3 条评论
    2
  • 卖薪沽酒
    2022-06-16
    不简单, 来来回回来到了13课程, 关于课后问题, 习惯用ximd 梳理, 有兴趣的同学可以看看,一起加油https://www.cnblogs.com/iwssea/p/16383412.html

    作者回复: 很强

    
    1