How to decompress the gzip compressed file by analyzing the kernel

Source: Internet
Author: User
Article Title: how to extract gzip compressed files by analyzing the kernel. Linux is a technology channel of the IT lab in China. Includes basic categories such as desktop applications, Linux system management, kernel research, embedded systems, and open source.
Author: opera
Overview
----
1) Linux's initial kernel image is stored in zImage or bzImage as a gzip compressed file.
The Code decompress it to the beginning of 1 MB of memory. during kernel initialization, if a compressed initrd image is loaded, the kernel will decompress the image to the memory disk. lib/inflate is used during the decompression process. c file.
2) inflate. c is separated from the gzip source program and contains some direct references to global data.
To be directly embedded into the code, the. gzip file is always searched for duplicate strings within the range of 32 KB.
Encoding. during decompression, a buffer with at least 32 K bytes is required. It is defined as window [WSIZE].
Inflate. c Use get_byte () to read the input file, which is defined as a macro to improve efficiency. The input buffer pointer must
It is defined as inptr, and inflate. c has a reduction operation on it. inflate. c calls flush_window () to output window
The encoded byte string in the buffer. Each output length is expressed by the outcnt variable. In flush_window (),
CRC must be calculated for the output byte string and the crc variable must be refreshed. makecrc () is called before gunzip () is called to start decompression ()
Initialize the CRC calculation table. The final result returned by gunzip () is 0, indicating that the extraction is successful.
3) zImage or bzImage consists of 16-bit Boot Code and 32-bit kernel self-extracting image. For zImage
The self-decompressed kernel image is loaded to the physical address 0x1000, and the kernel is extracted to 1 MB. For bzImage, the kernel self-decompress
When the pressure image is loaded to the starting point of 1 MB, the kernel is decompressed into two fragments, one starting from the physical address 0x2000-0x90000,
Another area starting from the high-end decompression image and starting from 1 m is not smaller than the maximum length of the low-end fragment. After decompression,
These two fragments are merged to the starting position of 1 MB.
Code for extracting the image file from the root memory disk
--------------------------
Code:
; Drivers/block/rd. c
# Ifdef BUILD_CRAMDISK
/*
* Gzip declarations
*/
# Define OF (args) args; macro used for function prototype Declaration
# Ifndef memzero
# Define memzero (s, n) memset (s), 0, (n ))
# Endif
Typedef unsigned char uch; defines the three data types used by inflate. c
Typedef unsigned short ush;
Typedef unsigned long ulg;
# Define INBUFSIZ 4096 user input buffer size
# Define WSIZE 0x8000/* window size -- must be a power of two, and */
/* At least 32 K for zip's deflate method */
  
Static uch * inbuf; user input buffer, independent of inflate. c
Static uch * window; decompress the window
Static unsigned insize;/* valid bytes in inbuf */
Static unsigned inptr;/* index of next byte to be processed in inbuf */
Static unsigned outcnt;/* bytes in output buffer */
Static int exit_code;
Static long bytes_out; total extract output length, independent of inflate. c
Static struct file * crd_infp, * crd_outfp;
# Define get_byte () (inptr <insize? Inbuf [inptr ++]: fill_inbuf () reads a byte in the input buffer.
/* Diagnostic functions (stubbed out) */some debugging macros
# Define Assert (cond, msg)
# Define Trace (x)
# Define Tracev (x)
# Define Tracevv (x)
# Define Tracec (c, x)
# Define Tracecv (c, x)
# Define STATIC static
Static int fill_inbuf (void );
Static void flush_window (void );
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 **);
# Include "../lib/inflate. c"
Static void _ init * malloc (int size)
{
Return kmalloc (size, GFP_KERNEL );
}
Static void _ init free (void * where)
{
Kfree (where );
}
Static void _ init gzip_mark (void ** ptr)
{
; Read a user tag
}
Static void _ init gzip_release (void ** ptr)
{
; Return user mark
}
/* ===================================================== ============================================
* Fill the input buffer. This is called only when the buffer is empty
* And at least one byte is really needed.
*/
Static int _ init fill_inbuf (void) Fill in the input buffer
{
If (exit_code) return-1;
Insize = crd_infp-> f_op-> read (crd_infp, inbuf, INBUFSIZ,
& Crd_infp-> f_pos );
If (insize = 0) return-1;
Inptr = 1;
Return inbuf [0];
}
  
/* ===================================================== ============================================
* Write the output windows window [0 .. outcnt-1] and update crc and bytes_out.
* (Used for the decompressed data only .)
*/
Static void _ init flush_window (void) Output outcnt byte strings in the window Buffer
{
Ulg c = crc;/* temporary variable */
Unsigned n;
Uch * in, ch;
Crd_outfp-> f_op-> write (crd_outfp, window, outcnt, & crd_outfp-> f_pos );
In = window;
For (n = 0; n <outcnt; n ++ ){
Ch = * in ++;
C = crc_32_tab [(int) c ^ ch) & 0xff] ^ (c> 8); Calculate the CRC of the output string
}
Crc = c;
Bytes_out + = (ulg) outcnt; refresh the total number of bytes
Outcnt = 0;
}
Static void _ init error (char * x) decompress the function called when an error occurs.
{
Printk (KERN_ERR "% s", x );
Exit_code = 1;
}
Static int _ init
Crd_load (struct file * fp, struct file * outfp)
{
Int result;
Insize = 0;/* valid bytes in inbuf */
Inptr = 0;/* index of next byte to be processed in inbuf */
Outcnt = 0;/* bytes in output buffer */
Exit_code = 0;
Bytes_out = 0;
Crc = (ulg) 0 xffffffl;/* shift register contents */
Crd_infp = fp;
Crd_outfp = outfp;
Inbuf = kmalloc (INBUFSIZ, GFP_KERNEL );
If (inbuf = 0 ){
Printk (KERN_ERR "RAMDISK: Couldn't allocate gzip buffer \ n ");
Return-1;
}
Window = kmalloc (WSIZE, GFP_KERNEL );
If (window = 0 ){
Printk (KERN_ERR "RAMDISK: Couldn't allocate gzip window \ n ");
Kfree (inbuf );
Return-1;
}
Makecrc ();
Result = gunzip ();
Kfree (inbuf );
Kfree (window );
Return result;
}
# Endif/* BUILD_CRAMDISK */
32-bit kernel self-extracting code
------------------
; Arch/i386/boot/compressed/head. S
. Text
# Include
# Include
. Globl startup_32 for zImage, the entry address is 0x1000; For bzImage, the entry address is 0x101000.
Startup_32:
Cld
Cli
Movl $ (_ KERNEL_DS), % eax
Movl % eax, % ds
Movl % eax, % es
Movl % eax, % fs
Movl % eax, % gs
Lss SYMBOL_NAME (stack_start), % esp # the stack of the Self-extracting code is a 16 K byte array defined in misc. c.
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
/*
* Initialize eflags. Some BIOS's leave bits like NT set. This wowould
* Confuse the debugger if this code is traced.
* XXX-best to initialize before switching to protected mode.
*/
Pushl $0
Popfl
/*
* Clear BSS Clear the BSS segment of the decompression program
*/
Xorl % eax, % eax
Movl $ SYMBOL_NAME (_ edata), % edi
Movl $ SYMBOL_NAME (_ end), % ecx
Subl % edi, % ecx
Cld
Rep
Stosb
/*
* Do the decompression, and jump to the new kernel ..
*/
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 # If the returned value is non-zero, it indicates that the kernel is decompressed into two segments: low-end and high-end.
Jnz 3f
Popl % esi # discard address
Popl % esi # real mode pointer
Xorl % ebx, % ebx
Ljmp $ (_ KERNEL_CS), $0x100000 # Run start_kernel
/*
* We come here, if we were loaded high.
  
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.