xv6/bootasm.S + xv6/bootmain.c

xv6/bootasm.S

 1 #include "asm.h"
 2 #include "memlayout.h"
 3 #include "mmu.h"
 4
 5 # Start the first CPU: switch to 32-bit protected mode, jump into C.
 6 # The BIOS loads this code from the first sector of the hard disk into
 7 # memory at physical address 0x7c00 and starts executing in real mode
 8 # with %cs=0 %ip=7c00.
 9
10 .code16 # Assemble for 16-bit mode
11 .globl start
12 start:
13 cli # BIOS enabled interrupts; disable
14
15 # Zero data segment registers DS, ES, and SS.
16 xorw %ax,%ax # Set %ax to zero
17 movw %ax,%ds # -> Data Segment
18 movw %ax,%es # -> Extra Segment
19 movw %ax,%ss # -> Stack Segment
20
21 # Physical address line A20 is tied to zero so that the first PCs
22 # with 2 MB would run software that assumed 1 MB. Undo that.
23 seta20.1:
24 inb $0x64,%al # Wait for not busy
25 testb $0x2,%al
26 jnz seta20.1
27
28 movb $0xd1,%al # 0xd1 -> port 0x64
29 outb %al,$0x64
30
31 seta20.2:
32 inb $0x64,%al # Wait for not busy
33 testb $0x2,%al
34 jnz seta20.2
35
36 movb $0xdf,%al # 0xdf -> port 0x60
37 outb %al,$0x60
38
39 # Switch from real to protected mode. Use a bootstrap GDT that makes
40 # virtual addresses map directly to physical addresses so that the
41 # effective memory map doesn’t change during the transition.
42 lgdt gdtdesc
43 movl %cr0, %eax
44 orl $CR0_PE, %eax
45 movl %eax, %cr0
46
47
48
49
50
51 # Complete transition to 32-bit protected mode by using long jmp
52 # to reload %cs and %eip. The segment descriptors are set up with no
53 # translation, so that the mapping is still the identity mapping.
54 ljmp $(SEG_KCODE<<3), $start32
55
56 .code32 # Tell assembler to generate 32-bit code now.
57 start32:
58 # Set up the protected-mode data segment registers
59 movw $(SEG_KDATA<<3), %ax # Our data segment selector
60 movw %ax, %ds # -> DS: Data Segment
61 movw %ax, %es # -> ES: Extra Segment
62 movw %ax, %ss # -> SS: Stack Segment
63 movw $0, %ax # Zero segments not ready for use
64 movw %ax, %fs # -> FS
65 movw %ax, %gs # -> GS
66
67 # Set up the stack pointer and call into C.
68 movl $start, %esp
69 call bootmain
70
71 # If bootmain returns (it shouldn’t), trigger a Bochs
72 # breakpoint if running under Bochs, then loop.
73 movw $0x8a00, %ax # 0x8a00 -> port 0x8a00
74 movw %ax, %dx
75 outw %ax, %dx
76 movw $0x8ae0, %ax # 0x8ae0 -> port 0x8a00
77 outw %ax, %dx
78 spin:
79 jmp spin
80
81 # Bootstrap GDT
82 .p2align 2 # force 4 byte alignment
83 gdt:
84 SEG_NULLASM # null seg
85 SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg
86 SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg
87
88 gdtdesc:
89 .word (gdtdesc - gdt - 1) # sizeof(gdt) - 1
90 .long gdt # address gdt

xv6/bootmain.c

 1 // Boot loader.
 2 //
 3 // Part of the boot sector, along with bootasm.S, which calls bootmain().
 4 // bootasm.S has put the processor into protected 32-bit mode.
 5 // bootmain() loads an ELF kernel image from the disk starting at
 6 // sector 1 and then jumps to the kernel entry routine.
 7
 8 #include "types.h"
 9 #include "elf.h"
10 #include "x86.h"
11 #include "memlayout.h"
12
13 #define SECTSIZE 512
14
15 void readseg(uchar*, uint, uint);
16
17 void
18 bootmain(void)
19 {
20     struct elfhdr *elf;
21     struct proghdr *ph, *eph;
22     void (*entry)(void);
23     uchar* pa;
24
25     elf = (struct elfhdr*)0x10000; // scratch space
26
27     // Read 1st page off disk
28     readseg((uchar*)elf, 4096, 0);
29
30     // Is this an ELF executable?
31     if(elf->magic != ELF_MAGIC)
32         return; // let bootasm.S handle error
33
34     // Load each program segment (ignores ph flags).
35     ph = (struct proghdr*)((uchar*)elf + elf->phoff);
36     eph = ph + elf->phnum;
37     for(; ph < eph; ph++){
38         pa = (uchar*)ph->paddr;
39         readseg(pa, ph->filesz, ph->off);
40         if(ph->memsz > ph->filesz)
41             stosb(pa + ph->filesz, 0, ph->memsz - ph->filesz);
42     }
43
44     // Call the entry point from the ELF header.
45     // Does not return!
46     entry = (void(*)(void))(elf->entry);
47     entry();
48 }
49
50
51 void
52 waitdisk(void)
53 {
54     // Wait for disk ready.
55     while((inb(0x1F7) & 0xC0) != 0x40)
56         ;
57 }
58
59 // Read a single sector at offset into dst.
60 void
61 readsect(void *dst, uint offset)
62 {
63     // Issue command.
64     waitdisk();
65     outb(0x1F2, 1); // count = 1
66     outb(0x1F3, offset);
67     outb(0x1F4, offset >> 8);
68     outb(0x1F5, offset >> 16);
69     outb(0x1F6, (offset >> 24) | 0xE0);
70     outb(0x1F7, 0x20); // cmd 0x20 - read sectors
71
72     // Read data.
73     waitdisk();
74     insl(0x1F0, dst, SECTSIZE/4);
75 }
76
77 // Read ’count’ bytes at ’offset’ from kernel into physical address ’pa’.
78 // Might copy more than asked.
79 void
80 readseg(uchar* pa, uint count, uint offset)
81 {
82     uchar* epa;
83
84     epa = pa + count;
85
86     // Round down to sector boundary.
87     pa -= offset % SECTSIZE;
88
89     // Translate from bytes to sectors; kernel starts at sector 1.
90     offset = (offset / SECTSIZE) + 1;
91
92     // If this is too slow, we could read lots of sectors at a time.
93     // We’d write more to memory than asked, but it doesn’t matter --
94     // we load in increasing order.
95     for(; pa < epa; pa += SECTSIZE, offset++)
96         readsect(pa, offset);
97 }
时间: 2024-12-15 20:13:47

xv6/bootasm.S + xv6/bootmain.c的相关文章

XV6操作系统剖析_1.1 XV6操作系统的安装与使用

1.1  XV6操作系统的安装与使用 麻省理工大学的网站上 http://pdos.csail.mit.edu/6.828/2011/xv6.html,已经对XV6的来龙去脉及如何下载做了较详细的介绍.这里我们以32位的Ubuntu12.04为例,简单介绍一下如何通过x86模拟器Bochs来运行XV6操作系统. XV6操作系统是可以运行在多核结构的X86平台上,我们需要支持SMP功能的Bochs模拟器,可从http://sourceforge.net/projects/bochs/files/b

xv6 + Qemu 在Ubuntu下编译运行教程【转】

转自:https://blog.csdn.net/yinglang19941010/article/details/49310111 如果想要离线看教程,可以下载该 文档 一.使用工具说明 1.       xv6 源代码文件(以下三选一) 1)http://download.csdn.net/detail/yinglang19941010/9201421 (我使用的是这个,怕出错的同学可以下这个) 2)https://github.com/yinglang/Xv6  或 3)http://zo

XV6操作系统代码阅读心得(三):锁

锁是操作系统中实现进程同步的重要机制. 基本概念 临界区(Critical Section)是指对共享数据进行访问与操作的代码区域.所谓共享数据,就是可能有多个代码执行流并发地执行,并在执行中可能会同时访问的数据. 同步(Synchronization)是指让两个或多个进程/线程能够按照程序员期望的方式来协调执行的顺序.比如,让A进程必须完成某个操作后,B进程才能执行.互斥(Mutual Exclusion)则是指让多个线程不能够同时访问某些数据,必须要一个进程访问完后,另一个进程才能访问. 当

ucore lab1 bootloader学习笔记

---恢复内容开始--- 开机流程回忆 以Intel 80386为例,计算机加电后,CPU从物理地址0xFFFFFFF0(由初始化的CS:EIP确定,此时CS和IP的值分别是0xF000和0xFFF0))开始执行.在0xFFFFFFF0这里只是存放了一条跳转指令,通过跳转指令跳到BIOS例行程序起始点.BIOS做完计算机硬件自检和初始化后,会选择一个启动设备(例如软盘.硬盘.光盘等),并且读取该设备的第一扇区(即主引导扇区或启动扇区)到内存一个特定的地址0x7c00处,然后CPU控制权会转移到那

lab 1实验报告

练习1:理解通过make生成执行文件的过程.   生成 bin/kern 部分 生成 init.o 生成 readline.o 生成 stdio.o 生成 kdebug.o 生成 kmonitor.o 生成 panic.o 生成 clock.o 生成 console.o 生成 intr.o 生成 picirq.o 生成 trap.o 生成 trapentry.o 生成 vectors.o 生成 pmm.o 生成 printfmt.o 生成 string.o   用上面 .o 文件连接生成 bin

操作系统ucore lab1实验报告

操作系统lab1实验报告 [练习1] 理解通过 make 生成执行文件的过程.(要求在报告中写出对下述问题的回答) 在此练习中,大家需要通过阅读代码来了解: 1. 操作系统镜像文件 ucore.img 是如何一步一步生成的?(需要比较详细地解释 Makefile 中 每一条相关命令和命令参数的含义,以及说明命令导致的结果) 2. 一个被系统认为是符合规范的硬盘主引导扇区的特征是什么? [练习1.1] 1.生成ucore.img需要kernel和bootblock 生成ucore.img的代码如下

实现操作系统TOS lab1

实验目的: 操作系统是一个软件,也需要通过某种机制加载并运行它. 在这里我们将通过另外一个更加简单的软件-bootloader来完成这些工作,为此,我们需要完成一个能够切换到x86的保护模式并显示字符的bootloader,为启动操作系统TOS来做准备. lab1提供了一个非常小的boot loader和 TOS ,真个bootloader执行代码小于512字节(一个扇区),这样才能放到硬盘的主引导扇区中. 通过分析和实现这个boot loader和TOS ,可以了解到: 计算机原理 cpu的编

lab1的实验练习答案

# Lab1 report ## [练习1] [练习1.1] 操作系统镜像文件 tos.img 是如何一步一步生成的?(需要比较详细地解释 Makefile 中 每一条相关命令和命令参数的含义,以及说明命令导致的结果) bin/tos.img | 生成tos.img的相关代码为 | (TOSIMG):(kernel) (bootblock)|(V)dd if=/dev/zero of=@count=10000|(V)dd if=(bootblock)of=@ conv=notrunc | (V)

homework1:boot xv6

Homework 1 boot xv6 首先在启动块(bootasm.S)的起始位置0x7c00处设置一个断点.单步执行说明(在gdb提示符下键入si).在bootasm.S中的哪个地方初始化了堆栈指针? bootasm.S 在 movl $start, %esp 处设置了堆栈指针,将栈顶指向了 0x7c00. 单步执行对bootmain的调用:现在堆栈上有什么? call bootmain 位于物理地址 0x7c48,调用 bootmian 后,栈内有如下内容: ? 其中栈顶 0x7bfc 处