解压缩内核

4.1.2 解压缩内核

解压缩内核使用的是decompress_kernel函数,来自arch/x86/boot/compressed/misc.c

 

301asmlinkage void decompress_kernel(void *rmode, memptr heap,

 302                                  unsigned char *input_data,

 303                                  unsigned long input_len,

 304                                  unsigned char *output)

 305{

 306        real_mode = rmode;

 307

 308        if (real_mode->hdr.loadflags & QUIET_FLAG)

 309                quiet = 1;

 310

 311        if (real_mode->screen_info.orig_video_mode == 7) {

 312                vidmem = (char *) 0xb0000;

 313                vidport = 0x3b4;

 314        } else {

 315                vidmem = (char *) 0xb8000;

 316                vidport = 0x3d4;

 317        }

 318

 319        lines = real_mode->screen_info.orig_video_lines;

 320        cols = real_mode->screen_info.orig_video_cols;

 321

 322        free_mem_ptr     = heap;        /* Heap */

 323        free_mem_end_ptr = heap + BOOT_HEAP_SIZE;

 324

 325        if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))

 326                error("Destination address inappropriately aligned");

 327#ifdef CONFIG_X86_64

 328        if (heap > 0x3fffffffffffUL)

 329                error("Destination address too large");

 330#else

 331        if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff))

 332                error("Destination address too large");

 333#endif

 334#ifndef CONFIG_RELOCATABLE

 335        if ((unsigned long)output != LOAD_PHYSICAL_ADDR)

 336                error("Wrong destination address");

 337#endif

 338

 339        if (!quiet)

 340                putstr("/nDecompressing Linux... ");

 341        decompress(input_data, input_len, NULL, NULL, output, NULL, error);

 342        parse_elf(output);

 343        if (!quiet)

 344                putstr("done./nBooting the kernel./n");

 345        return;

 346}

 

看到他的参数,共有5个,是刚才依次压栈而得到的。第一个是压入的output(还记得吧,倒着来的),在刚才的131行看到的,来自z_extract_offset_negative,用于作为解压缩的缓存首地址;第二个,input_len,其值等于z_input_len,表示待压缩内核大小;第三个,input_data,来自input_data,表示待压缩内核地址;第四个参数,heap32位下是32位,来自boot_heap,表示解压缩阶段的堆;最后一个参数,rmode,来自我们刚才用到的esi寄存器,表示刚才拷贝之前内核映像地址。

 

假设我配置的是CONFIG_KERNEL_BZIP2,那么会调用顶层lib/decompress_bunzip2.c中的decompress函数,最终会调用位于同一文件的bunzip2函数(注意,在我们制作bzImage的时候使用的压缩程序只有一个,如果指定的bunzip2,那么都在decompress_bunzip2.c里):

 

674/* Example usage: decompress src_fd to dst_fd.  (Stops at end of bzip2 data,

 675   not end of file.) */

 676STATIC int INIT bunzip2(unsigned char *buf, int len,

 677                        int(*fill)(void*, unsigned int),

 678                        int(*flush)(void*, unsigned int),

 679                        unsigned char *outbuf,

 680                        int *pos,

 681                        void(*error_fn)(char *x))

 682{

 683        struct bunzip_data *bd;

 684        int i = -1;

 685        unsigned char *inbuf;

 686

 687        set_error_fn(error_fn);

 688        if (flush)

 689                outbuf = malloc(BZIP2_IOBUF_SIZE);

 690

 691        if (!outbuf) {

 692                error("Could not allocate output bufer");

 693                return RETVAL_OUT_OF_MEMORY;

 694        }

 695        if (buf)

 696                inbuf = buf;

 697        else

 698                inbuf = malloc(BZIP2_IOBUF_SIZE);

 699        if (!inbuf) {

 700                error("Could not allocate input bufer");

 701                i = RETVAL_OUT_OF_MEMORY;

 702                goto exit_0;

 703        }

 704        i = start_bunzip(&bd, inbuf, len, fill);

 705        if (!i) {

 706                for (;;) {

 707                        i = read_bunzip(bd, outbuf, BZIP2_IOBUF_SIZE);

 70

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值