Steps to make a change to a binary (already compiled) kernel
 

Steps to make a change to a binary (already compiled) kernel

 

This post was last updated on May 27th, 2020 at 04:05 pm

Steps to make a change to a binary (already compiled) kernel

Take a bzImage
Unpack it with mkvmlinux
This will provide you with 3 parts:
bootsector, setup, and system
(Currently the unpacker gives you no permissions, so do chmod a+rw bootsector setup system)

system is composed of (at least) 2 parts
header and data

The data section is the kernel proper in gzip format. You will notice the data (gzipped kernel) begins with the gzip signiture of “1f 8b 08”. Just prior to this is just a handfull of values and a lot of “00” padding. The data section in my “system” starts around offset 3650 (IIRC – If I Recall Correctly).

Note what the offset is, then convert that hex value to decimal

bc
ibase=16
3650

Then dd out the header and data
dd if=system of=header bs=1 count=13904
dd if=system of=kernel.gz bs=1 skip=13904

Now unzip the kernel:
gunzip kernel.gz

Now convert to hex and then make any modifications you need to the kernel.

xxd -g 1 kernel kernel.hex

My need is to change the Serial I/O port from 0x3f8 to 0x400, so I find my appropriate section which has “c2 01 00 f8 03” (note that most everything has reverse order), then I make my change to “c2 01 00 00 04”. Now it’s time to repack.

Convert from hex back to binary:

xxd -r kernel.hex kernel.new

Compress the kernel

cat kernel.new | gzip -n9 > kernel.new.gz

The tail end of the header contains the length of the ?gzipped? kernel. So do a ls -l kernel.new.gz and convert that to hex:

bc
obase=16
110506

So that means that you have to convert the header to hex, update the size, then repack it:

xxd -g 1 header header.hex

xxd -r header.hex header.new

Put back the header and kernel:
cat header.new kernel.new.gz > system.new

Now put back the 3 main pieces:

./mkvmlinuz -b -o bzImage.new bootsect setup system.new

Now boot on the new bzImage

Notes:
Make sure that bytes 501 and 500 of are still able to contain the size (in blocks of 16, rounded up) of the system.new.

The above doesn’t have accurate numbers with each of the examples yet.

In the above example my gzipped kernel was 2 bytes larger than the previous. Without updating the header size info I got “ran out of input data”. Now after updating the header size info, I get something like “length error”. So I am still missing a value somewhere.

Previous Serial Console in Linux
Next PL5000 Debian 30.2-6.x
 

About author

shibaa987
shibaa987 268 posts

Linux kernel developer and a firmware developer with an experience of 10+ years.

View all posts by this author →

You might also like

How To 0 Comments

How To Check System Hardware Information In Ubuntu 20.04 LTS?

This post was last updated on August 1st, 2020 at 12:20 pmA computer system is consists of different types of hardware such as processor, RAM, hard disk, network cards, etc.

FreeBSD 0 Comments

How To Install And Configure Gnome Desktop in FreeBSD?

This post was last updated on August 1st, 2020 at 12:05 pmFreeBSD is a free and open-source Unix-like operating system descended from the Berkeley Software Distribution. It is used to power

How To 0 Comments

Linux I/O Redirection

This post was last updated on May 26th, 2020 at 03:07 pmCool commands The following command saves stdout and stderr to the files “out” and “err”, respectively. [[email protected] /root]# ./cmd

0 Comments

No Comments Yet!

You can be first to comment this post!

Leave a Reply