设为首页 加入收藏

TOP

Linux的初始内核自解压分析(二)
2014-11-24 01:34:44 来源: 作者: 【 】 浏览:8
Tags:Linux 初始 内核 解压 分析
,%gs
  lss SYMBOL_NAME(stack_start),%esp # 自解压代码的堆栈为misc.c中定义的16K字节的数组
  xorl %eax,%eax
  1: incl %eax # check that A20 really IS enabled
  movl %eax,0x000000 # loop forever if it isn't
  cmpl %eax,0x100000
  je 1b
  
  pushl $0
  popfl
  
  xorl %eax,%eax
  movl $ SYMBOL_NAME(_edata),%edi
  movl $ SYMBOL_NAME(_end),%ecx
  subl %edi,%ecx
  cld
  rep
  stosb
  
  subl $16,%esp # place for structure on the stack
  movl %esp,%eax
  pushl %esi # real mode pointer as second arg
  pushl %eax # address of structure as first arg
  call SYMBOL_NAME(decompress_kernel)
  orl %eax,%eax # 如果返回非零,则表示为内核解压为低端和高端的两个片断
  jnz 3f
  popl %esi # discard address
  popl %esi # real mode pointer
  xorl %ebx,%ebx
  ljmp $(__KERNEL_CS), $0x100000 # 运行start_kernel
  
  3:
  movl $move_routine_start,%esi
  movl $0x1000,%edi
  movl $move_routine_end,%ecx
  subl %esi,%ecx
  addl $3,%ecx
  shrl $2,%ecx # 按字取整
  cld
  rep
  movsl # 将内核片断合并代码复制到0x1000区域, 内核的片段起始为0x2000
  popl %esi # discard the address
  popl %ebx # real mode pointer
  popl %esi # low_buffer_start 内核低端片段的起始地址
  popl %ecx # lcount 内核低端片段的字节数量
  popl %edx # high_buffer_start 内核高端片段的起始地址
  popl %eax # hcount 内核高端片段的字节数量
  movl $0x100000,%edi 内核合并的起始地址
  cli # make sure we don't get interrupted
  ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine
  
  move_routine_start:
  movl %ecx,%ebp
  shrl $2,%ecx
  rep
  movsl # 按字拷贝第1个片段
  movl %ebp,%ecx
  andl $3,%ecx
  rep
  movsb # 传送不完全字
  movl %edx,%esi
  movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0
  addl $3,%ecx
  shrl $2,%ecx # 按字对齐
  rep
  movsl # 按字拷贝第2个片段
  movl %ebx,%esi # Restore setup pointer
  xorl %ebx,%ebx
  ljmp $(__KERNEL_CS), $0x100000 # 运行start_kernel
  move_routine_end:
  ; arch/i386/boot/compressed/misc.c
  
  #define OF(args) args
  #define STATIC static
  #undef memset
  #undef memcpy
  #define memzero(s, n) memset ((s), 0, (n))
  ypedef unsigned char uch;
  typedef unsigned short ush;
  typedef unsigned long ulg;
  #define WSIZE 0x8000
  
  static uch *inbuf;
  static uch window[WSIZE];
  static unsigned insize = 0;
  static unsigned inptr = 0;
  static unsigned outcnt = 0;
  
  #define ASCII_FLAG 0x01
  #define CONTINUATION 0x02
  #define EXTRA_FIELD 0x04
  #define ORIG_NAME 0x08
  #define COMMENT 0x10
  #define ENCRYPTED 0x20
  #define RESERVED 0xC0
  #define get_byte() (inptr
  
  #ifdef DEBUG
  # define Assert(cond,msg) {if(!(cond)) error(msg);}
  # define Trace(x) fprintf x
  # define Tracev(x) {if (verbose) fprintf x ;}
  # define Tracevv(x) {if (verbose>1) fprintf x ;}
  # define Tracec(c,x) {if (verbose (c)) fprintf x ;}
  # define Tracecv(c,x) {if (verbose>1 (c)) fprintf x ;}
  #else
  # define Assert(cond,msg)
  # define Trace(x)
  # define Tracev(x)
  # define Tracevv(x)
  # define Tracec(c,x)
  # define Tracecv(c,x)
  #endif
  static int fill_inbuf(void);
  static void flush_window(void);
  static void error(char *m);
  static void gzip_mark(void **);
  static void gzip_release(void **);
  
  static unsigned char *real_mode;
  #define EXT_MEM_K (*(unsigned short *)(real_mode + 0x2))
  #ifndef STANDARD_MEMORY_BIOS_CALL
  #define ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0))
  #endif
  #define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
  extern char input_data[];
  extern int input_len;
  static long bytes_out = 0;
  static uch *output_data;
  static unsigned long output_ptr = 0;
  static void *malloc(int size);
  static void free(void *where);
  static void error(char *m);
  static void gzip_mark(void **);
  static void gzip_release(void **);
  static void puts(const char *);
  extern int end;
  static long free_mem_ptr = (long)
  static long free_mem_end_ptr;
  #define INPLACE_MOVE_ROUTINE 0x1000 内核片段合并代码的运行地址
  #define LOW_BUFFER_START 0x2000 内核低端解压片段的起始地址
  #de
首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Linux+C语言:数字图像处理源程序 下一篇深度介绍Linux内核是如何工作的

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: