标签 Kernel 下的文章

Retired 'bootsect.S'

We know that the latest linux kernel version is 2.6.x, which is different from the ‘old kernels’ in booting. The ‘bootsect.S’, which used to make the kernel image in the floppy disk bootable in the early days, becomes useless in linux kernel 2.6.x today, although it is still a part of the kernel image.

We know that ‘bootsect.S’ is usu placed in the first 512 bytes of the kernel image and installed in the first sector of some medium on which the kernel image is installed. the mediums usu include hard disk (or the active partition of the hard disk) and floppy disk. As a minimal ‘bootloader’ included in kernel images of earlier linux versions up to the 2.4, the ‘bootsect.S’ is in duty bound to copy the left kernel image from medium to main memory when we boot linux from the floppy disk and then execute the loaded code in order to complete its mission. when we boot linux from hard disk, the ‘bootsect.S’ does nothing actively but to be checked by other booting routine stored in BIOS(Basic Input/Output System) or MBR(Master Boot Record). Today if you wanna boot linux 2.6.x from a floppy disk, you have to select a suitable bootloader yourself, just like that you boot linux from hard disk, since the ‘bootsect.S’ has retired.

Here list the source code of ‘bootsect.S’ and some comments of mine. let us go and see what the retired ‘bootsect.S’ really does! (my comments usu occur following the symbol ‘!’)

/*
 * bootsect.S  Copyright (C) 1991, 1992 Linus Torvalds
 *
 * modified by Drew Eckhardt
 * modified by Bruce Evans (bde)
 * modified by Chris Noe (May 1999) (as86 -> gas)
 * gutted by H. Peter Anvin (Jan 2003)
 *
 * BIG FAT NOTE: We’re in real mode using 64k segments.  Therefore segment
 * addresses must be multiplied by 16 to obtain their respective linear
 * addresses. To avoid confusion, linear addresses are written using leading
 * hex while segment addresses are written as segment:offset.
 *
 * ! $(linux-2.6.15.3_dir)/arch/i386/bootsect.S
 */

/* ! I found this header file in $(linux-2.6.15.3_dir)/include/asm-i386 */
#include

/*
 * ! DEF_INITSEG   0×9000
 * ! DEF_SYSSEG    0×1000
 * ! DEF_SETUPSEG  0×9020
 * ! DEF_SYSSIZE   0x7F00
 * ! These macros above are defined in ‘boot.h’ and
 * ! the values of the first three of them
 * ! used to be stored into ‘cs’ register
 */
SETUPSECTS = 4   /* default nr of setup-sectors */
BOOTSEG  = 0x07C0  /* original address of boot-sector */
INITSEG  = DEF_INITSEG  /* we move boot here – out of the way */
SETUPSEG = DEF_SETUPSEG  /* setup starts here */
SYSSEG  = DEF_SYSSEG  /* system loaded at 0×10000 (65536) */
SYSSIZE  = DEF_SYSSIZE  /* system size: # of 16-byte clicks */
                                            /* to be loaded */
/*
 * ! Here no matter what the ‘ROOT_DEV’ is is insignificant.
 * ! When kernel image builds, this ‘ROOT_DEV’ will be reset.
 * ! And so does ‘SWAP_DEV’.
 * ! ‘ROOT_DEV’ is variable which represents the type of the device
 * ! in which the root file system stores.
 * ! ‘ROOT_DEV = 0′ means the same type of floopy as boot. 
 */
ROOT_DEV = 0    /* ROOT_DEV is now written by "build" */
SWAP_DEV = 0   /* SWAP_DEV is now written by "build" */

#ifndef SVGA_MODE
#define SVGA_MODE ASK_VGA
#endif

#ifndef RAMDISK
#define RAMDISK 0
#endif

#ifndef ROOT_RDONLY
#define ROOT_RDONLY 1
#endif

/*
 * !Now we are running in 16-bit real mode, neither in
 * ! 32-bit real mode nor in 32-bit protected mode
 */
.code16
.text

.global _start
_start:

 /*
  * ! jmpl is an ‘jump’ instruction which
  * ! jumps between segments.
  * ! the instruction below first stores the
  * ! immediate number ‘$BOOTSEG’ into ‘CS’
  * ! register and stores the address of label
  * ! ‘start2′ into ‘EIP’ register, and then jumps
  * ! to label ‘start2′ to execute.
  * ! Now, R[%cs] = $BOOTSEG = 0x07C0
  */
 # Normalize the start address
 jmpl $BOOTSEG, $start2

start2:
 /*
  * ! initialize some general registers
  * ! R[%ds] = R[%es] = R[%ss] = 0x07C0
  * ! R[%sp] = 0x7c00
  */
 movw %cs, %ax
 movw %ax, %ds
 movw %ax, %es
 movw %ax, %ss
 movw $0x7c00, %sp

 /*
  * ! sti – set the interrupt flag
  * ! cld – clear ‘df’(direction flag). after it executed,
  * !       string operations will increment the index
  * !       registers (si and/or di) that they use
  */
 sti
 cld

 /*
  * ! store the address of ‘bugger_off_msg’
  * ! into register ‘si’(source-index register)
  */
 movw $bugger_off_msg, %si

 /*
  * ! this loop prints the ‘bugger_off_msg’ on screen
  * ! and jumps to ‘die’ label.
  */
msg_loop:
 /*
  * ! lodsb loads ‘al’ register with single memory
  * ! byte at the position pointed to by ‘si’ register
  * ! after the executing, the ‘si’ is automatically
  * ! increased or decreased according to the ‘df’.
  */
 lodsb
 andb %al, %al
 jz die
 movb $0xe, %ah
 movw $7, %bx
 int $0×10
 jmp msg_loop

 /*
  * ! the computer dies and you have to reboot.
  */
die:
 # Allow the user to press a key, then reboot
 xorw %ax, %ax

 /*
  * ! int 16h – bios interrupt to give user
  * ! a chance to enter something from the keyboard
  */
 int $0×16
 int $0×19

 # int 0×19 should never return.  In case it does anyway,
 # invoke the BIOS reset code…
 ljmp $0xf000,$0xfff0

bugger_off_msg:
 .ascii "Direct booting from floppy is no longer supported.\r\n"
 .ascii "Please use a boot loader program instead.\r\n"
 .ascii "\n"
 .ascii "Remove disk and press any key to reboot . . .\r\n"
 .byte 0

 # Kernel attributes; used by setup

 /*
  * ! variables below are important since
  * ! they would be refered by ‘setup.S’
  * ! the total size of these variables is
  * ! 15 bytes, 497 + 15 = 512 :)
  * ! the last word is ’0xAA55′, which indicates
  * ! this is a boot sector
  */
 .org 497
setup_sects: .byte SETUPSECTS
root_flags: .word ROOT_RDONLY
syssize: .word SYSSIZE
swap_dev: .word SWAP_DEV
ram_size: .word RAMDISK
vid_mode: .word SVGA_MODE
root_dev: .word ROOT_DEV
boot_flag: .word 0xAA55

/* ! end of bootsect.S */

Thus, we know that the retired ‘bootsect.S’ only tells us it has retired.

差异学习

看了dreamhead的那篇“差异程序员”,又恰逢在今天dreamhead在一封邮件中谈到其继续深入“向下学习”的想法,心里突然有了本篇题目这样的一个话题。

“差异程序员”(http://dreamhead.blogbus.com/logs/2005/12/1676755.html)

最近自己也在“向下走”,这和dreamhead的想法和做法不谋而合。dreamhead在其blog和邮件中都谈了其在“向下走”过程中的体会,“差异程序员”一篇dreamhead也是在告诉大家其不满足于只做应用一层的程序员,这也同样是我的一些想法。

想法有了,那我们是如何做的呢?mail中dreamhead谈到了他下一步的学习目标和计划,在我的回复mail中我也谈了我将在linux内核方面和编译技术方面作些努力的初步想法。dreamhead也马上谈了他关于这两方面的看法,这里引用少许,目的在对比:
“编译器的前端相对来说都是简单的,技术基本都是现成的,而且有现成的工具供人使用,当然,为了学习,还是自己尝试写一遍比较好。后端的东西才是真正复杂的,不同的平台不同的OS都会有不同的要求,之后,还有优化的技术,复杂度直线上升。… … 如果想了解OS运作,Linux内核显然过于庞大了,那本《自己动手写操作系统》则更为简单。一些基础的东西是类似的,只要理解了那个小内核,理解Linux只是更好的去体会更好的设计而已,因为所有的知识已经都各就其位了,一旦架构形成,剩下的只是不断完善了。”

看到这样的回复,我马上意识到:虽然都是向下走,但是我和dreamhead的目的不同,形成的想法就有了些差异。

我之所以想啃下编译,原因起初有二:一是在前不久的工作中想采用编译中的技术来完成项目中一个模块的功能;二是填补大学时没有学懂编译的遗憾,就是想弄懂那些三元式、四元式,让自己更专业一些。上星期看了“dragon book[注1]”作者的一席话又为我学习编译增加了一枚筹码,其大致意思就是:大多数学习编译的人一生都可能没有机会去创造一门语言,那么我们为什么还学习编译呢?其中一个原因就是编译技术中某些原理可以适用于一般应用软件的设计。比如词法分析器中的字符串匹配技术可用于文本编辑器、信息获取系统或者模式识别程序中。

对于学习linux内核我有以下几点考虑:首先一直在用户层使用内核提供的系统调用,比如fork,在很多Unix编程书中会讲到调用fork后子进程与父进程的异同,这些几乎就是应用程序员必须牢记的东西,一直很讨厌强记,遂想刨根问底的去看看fork的一些实现,这样弄清了其来龙去脉就再无须强记了,而弄清了这些后反过来又会让你更好的使用这些系统调用;其次,想在用户层程序中借鉴内核的优秀设计思想,比如缓冲技术,在内核中有在应用层也有,应用层完全可以参考内核中的某些优秀设计来实现;最后,了解操作系统内核会让你对计算机的体系的理解有一个质的飞跃。即使是计算机本科毕业的人又有多少敢说自己完全理解了计算机呢。

dreamhead以了解OS运作为目的向我们推荐《自己动手写操作系统》一书自然没错,带着这样的目的来学习这本书效果肯定也不错;但是对于我上面所说的那些目的,这本书也仅能满足一小部分,该书可以作为整个学习过程中的一个参考资料。这就是由于学习目的不同带来的一些差异性的东西。

差异学习没有对错之分,也没有好坏之分,只是因目的不同而已罢了。目的不同,学习的关注点和着重点就会不同,这样即使学习同一样的技术效果也不同。另外学习不是孤立的,沿着学习的主线方向会有很多旁支,如学习linux内核,你将会了解到CPU体系结构、存储器管理和算法理论等多方面的知识。

最近看到某一电视台播放的央视版“笑傲江湖”,情节中提到华山剑宗与气宗之争,当时自己就考虑“为何两派不二者兼修以达到前所未有之境界呢”,在后来的令狐冲无心插柳却达到了这一境界,想必那些在两宗相争中冤死的华山前辈们看到这一结局都后悔之极了吧。(开个玩笑,其实从古自今大凡争斗之事多源自“权势之争”)。令狐冲成为了绝顶高手又让我想到了“差异程序员”,要想成为“程序界”的令狐冲又何尝不需要“上下”兼修呢?起码dreamhead已经为我们作出了表率。

[注1]
“dragon book” — 《Compilers: Principles, Techniques and Tools》by Aho, Sethi and Ullman

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats