linux boot-protected_mode_jump

  1.  /* 
  2.   * The actual transition into protected mode 
  3.   * 文档: 
  4.   * /arch/x86/include/asm/segment.h 【1】 
  5.   * /arch/x86/boot/pmjump.S【本文】 
  6.   */  
  7.    
  8.  #include <asm/boot.h>  
  9.  #include <asm/processor-flags.h>  
  10.  #include <asm/segment.h>  
  11.  #include <linux/linkage.h>  
  12.    
  13.          .text  
  14.          .code16   /*16位汇编*/  
  15.    
  16.  /* 
  17.   * void protected_mode_jump(u32 entrypoint, u32 bootparams); 
  18.   * 内核中调用都是fastcall的,所以两个参数对应为: 
  19.   * EAX:参数1=boot_params.hdr.code32_start@pm.c 
  20.   * EDX=(u32)&boot_params + (ds() << 4)@pm.c 
  21.   * 根据前文,EAX中的值是压缩内核入口(未hook的情况下),EDX的值是 
  22.   * boot_params的地址。pm.c中ds值是loader加载内核载地址X所在的 
  23.   * 段,在document/x86/boot.txt中对X有描述。其它段自header.S进入 
  24.   * boot/main.c后,也没变过都等于X。 
  25.   */  
  26.     
  27.     
  28.   
  29.  GLOBAL(protected_mode_jump)            
  30.          movl    %edx, %esi          //esi指向boot_params  
  31.          xorl    %ebx, %ebx       //ebx清零         
  32.          movw    %cs, %bx            //bx存实模式代码段基址(等于X)  
  33.          /*            
  34.           * 将ebx左移4位再加上2f处的变量值再将结果存入2f所指的内存变量里。 
  35.           * 在这句命令之前,2f处原来的值是in_pm32的偏移值。这样做的意思是 
  36.           * 将cs:in_pm32计算出的线性(即in_pm32的物理)地址存入2f处的变量里。 
  37.           */  
  38.          shll    $4, %ebx               
  39.          addl    %ebx, 2f  
  40.          jmp     1f                      # Short jump to serialize on 386/486  
  41.  1:  
  42.    
  43.          movw    $__BOOT_DS, %cx  
  44.          movw    $__BOOT_TSS, %di  
  45.    
  46.          movl    %cr0, %edx  
  47.          orb     $X86_CR0_PE, %dl        # 这里开启cr0的保护模式位  
  48.          movl    %edx, %cr0  
  49.    
  50.          # Transition to 32-bit mode  
  51.           /*  
  52.            * 上面几句已经打开了保护模式,在临时的gdt中的代码段、数据段 
  53.            * 段基址被设置为0(在setup_gdt@pm.c中)。 
  54.            * 下面几句要通过保护模式的方法跳转到in_pm32处---用段选择子在gdt 
  55.            * 中选出cs所指的段,段基址加上偏移量(即2f处的内存值)进行跳转。上 
  56.            * 面说了,cs所指的gdt段段基址为0,所以实际跳转量也是2f处的值 
  57.            * (cs:in_pm32=in_pm32的物理地址值)。 
  58.            * 同时注意,实模式下用的是物理地址,而现在由于没开分页机制,所以计 
  59.            * 算出来的地址也是物理地址,这才保证了in_pm32能成功由下面指令跳 
  60.            * 过去---偏移是在实模式算出的,跳转是在开启了保护模式后进行的。 
  61.         */  
  62.          .byte   0x66, 0xea              # ljmpl 指令  
  63.  2:      .long   in_pm32                 # offset  
  64.          .word   __BOOT_CS               # 段选择子  
  65.  ENDPROC(protected_mode_jump)  
  66.    
  67.    
  68.    
  69.             
  70.       /* 
  71.        * 到这个函数时寄存器: 
  72.        * eax=压缩内核线性地址(protected_mode_jump的参数) 
  73.        * cs=__BOOT_CS代码段选择子 
  74.        * cx=__BOOT_DS段选择子 
  75.        * di=__BOOT_TSS段选择子          
  76.        */  
  77.          .code32                    /*32位的汇编*/  
  78.          .section ".text32","ax"    /*段定义*/  
  79.  GLOBAL(in_pm32)  
  80.          # Set up data segments for flat 32-bit mode  
  81.          /*将ds,es,fs,gs,ss等段选择子都设置成__BOOT_DS*/  
  82.          movl    %ecx, %ds  
  83.          movl    %ecx, %es  
  84.          movl    %ecx, %fs  
  85.          movl    %ecx, %gs  
  86.          movl    %ecx, %ss  
  87.          # The 32-bit code sets up its own stack, but this way we do have  
  88.          # a valid stack if some debugging hack wants to use it.  
  89.          /* 
  90.           * bx存放实模式cs值(内核地址X所在段),ebx等于cs左移过4位 
  91.           * sp在header.S中被设置成了相对于X的段基址的偏移量, 
  92.           * 现在esp=ebx+esp=栈顶指针,其实esp的值现在是个32位线性 
  93.           * 地址,值与实模式下线性地址相同。 
  94.           */  
  95.          addl    %ebx, %esp  
  96.    
  97.          # Set up TR to make Intel VT happy  
  98.          /*设置任务状态段寄存器*/  
  99.          ltr     %di  
  100.    
  101.          # Clear registers to allow for future extensions to the  
  102.          # 32-bit boot protocol  
  103.          /*所有寄存器清零*/  
  104.          xorl    %ecx, %ecx  
  105.          xorl    %edx, %edx  
  106.          xorl    %ebx, %ebx  
  107.          xorl    %ebp, %ebp  
  108.          xorl    %edi, %edi  
  109.    
  110.          # Set up LDTR to make Intel VT happy  
  111.          /*设置ldt的值,cx=0*/  
  112.          lldt    %cx  
  113.    
  114.          jmpl    *%eax                   # Jump to the 32-bit entrypoint  
  115.  ENDPROC(in_pm32)  
  116. /* 
  117.  * 到此为止,所有寄存器值: 
  118.  * edi=__BOOT_TSS 
  119.  * ecx,edx,ebx,ebp,edi=0 
  120.  * esi=boot_params 
  121.  * ds,es,fs,gs,ss=__BOOT_DS 
  122.  * cs=__BOOT_CS代码段选择子 
  123.  * eax=压缩内核入口 
  124.  * esp=合适的栈顶   
  125.  * 
  126.  * __BOOT_CS,__BOOT_DS,__BOOT_TSS的值分别指向临时gdt(pm.c)的第2,3,4项   
  127.  *  
  128.  */  

转载于:https://www.cnblogs.com/cybertitan/archive/2012/10/10/2719018.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值