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

Sibananda Sahu
Sibananda Sahu 211 posts

A Linux Kernel Developer and a Firmware Developer by profession. Have worked with few big companies: BROADCOM Corporation, Cypress Semiconductor, LSI Corporation, TOSHIBA Corporation, Western Digital; on various cutting edge technologies and product lines, such as: RAID storage Driver, SSD Firmware, WLAN Firmware etc. Having more than 9 years of experience in Software Engineering domain. Now, took a pledge to educate all aspirant students to teach about Linux Kernel Development.

View all posts by this author →

You might also like

How To 0 Comments

Kickstarter

This post was last updated on July 9th, 2020 at 01:54 pmks.cfg stuff: http://www.cpqlinux.com/ks-getting-started.html ks-merged-ks.cfg.html – A kickstart that works for 7.2, AS2.1, 7.3, 8.0, and 9 ks-create-merged-ks.cfg.sh.html – This

How To 0 Comments

How To Execute A Command With Superuser Privilege In FreeBSD?

This post was last updated on August 1st, 2020 at 10:28 amA superuser or root user is a most privileged user account in FreeBSD. It has access to all the

How To 1Comments

How to Fix Windows And Linux Showing Different Time In A Dual Boot System

This post was last updated on August 3rd, 2020 at 02:34 pmThere are many users who use a dual boot computer. Dual-booting Linux with Windows operating system has various advantages

0 Comments

No Comments Yet!

You can be first to comment this post!

Leave a Reply