linuxbashuefiobjdumpobjcopy

Elegant way to get text section (.cmdline) from efi stub


I want to read the .cmdline section of a systemd efi stub (where initramfs, kernel and cmdline was inserted).

$ cp linux.efi x.efi
$ objcopy --dump-section .cmdline=/dev/stdout x.efi
root=UUID=a6a7b817-0979-46f2-a6f7-dfa191f9fea4 rw
$ cmp linux.efi x.efi
linux.efi x.efi differ: byte 217, line 2

$ objcopy --dump-section .cmdline=/dev/stdout x.efi /dev/null
root=UUID=a6a7b817-0979-46f2-a6f7-dfa191f9fea4 rw
bf1f56f197f2e457f4b9b7a0abc6fcc07aba9a3dbd8ea7objcopy: /dev/null: file truncated
$ ls -alh /dev/null
crw-rw-rw- 1 root root 1, 3 Jun  9 19:01 /dev/null

$ objdump -s -j .cmdline x.efi | awk -F'  ' '{print $2}' | tr -d '\n'
root=UUID=a6a7b817-0979-46f2-a6f7-dfa191f9fea4 rw
7f4b9b7a0abc6fcc07aba9a3db

I think the first option is the most elegant one, but sadly it modifies the original file, which breaks secure boot. The second option creates an output file, which is not needed. Using /dev/null as file breaks /dev/null. So another file needs to be created and cleaned up afterwards (which I dont think is elegant, because it is totally not needed). The third option tries to parse the output, but has severe problems, when there is a double space in the cmdline. (Also I don't think writing a parser should be necessary here).

Is there a elegant solution? (Like telling objcopy to ignore the output file)

You can create an example file on systemd systems with:

objcopy --add-section .cmdline=<(echo -n "Test cmdline") /usr/lib/systemd/boot/efi/linuxx64.efi.stub x.efi

Here the .cmdline output should be Test cmdline.


Solution

  • You can use a bash process-substitution:

    objcopy -O binary --only-section=.cmdline x.efi >(cat)
    
    Test cmdline