[OE-core] [PATCH v3] boot-directdisk: mount root by MBR disk signature for Linux 3.8+

Jonathan Liu net147 at gmail.com
Wed Jul 10 03:08:30 UTC 2013


On 10 July 2013 07:48, Darren Hart <dvhart at linux.intel.com> wrote:
> On Wed, 2013-07-10 at 00:12 +1000, Jonathan Liu wrote:
>> The root device is currently set as /dev/hda2. However, this is
>> only correct if it's the first IDE drive. If booting off the first SATA
>> drive instead, it would be /dev/sda2. It's not the first drive, neither
>> /dev/hda2 or /dev/sda2 would be correct.
>>
>> The solution to this has typically been to use the filesystem UUID to
>> specify the root device but this requires extra support in the initrd.
>> Linux 3.8 introduces the ability to specify the root device using the
>> MBR disk signature and the partition number which is much simpler to
>> use and avoids the extra overhead of an initrd.
>>
>> This change uses the MBR disk signature to specify the root device when
>> using Linux 3.8+ and CONFIG_BLOCK (required for root=PARTUUID=)
>> is enabled in the kernel.
>>
>> This has been tested with QEMU x86 and Intel Desktop Board D2500HN using
>> an image recipe inheriting boot-directdisk and core-image.
>>
>> Signed-off-by: Jonathan Liu <net147 at gmail.com>
>> ---
>>  meta/classes/boot-directdisk.bbclass | 30 +++++++++++++++++++++++++++++-
>>  1 file changed, 29 insertions(+), 1 deletion(-)
>>
>> diff --git a/meta/classes/boot-directdisk.bbclass b/meta/classes/boot-directdisk.bbclass
>> index efeadab..f97060f 100644
>> --- a/meta/classes/boot-directdisk.bbclass
>> +++ b/meta/classes/boot-directdisk.bbclass
>> @@ -35,7 +35,9 @@ BOOTDD_EXTRA_SPACE ?= "16384"
>>  # Get the build_syslinux_cfg() function from the syslinux class
>>
>>  AUTO_SYSLINUXCFG = "1"
>> -SYSLINUX_ROOT ?= "root=/dev/sda2"
>> +SYSLINUX_FIXED_ROOT = "root=/dev/sda2"
>> +SYSLINUX_UUID_ROOT = "root=PARTUUID=${DISK_SIGNATURE}-02"
>
> Why  '=' and not '?=' for the above? Shouldn't the user be able to
> override these?
>
>> +SYSLINUX_ROOT ?= "${@'${SYSLINUX_UUID_ROOT}' if has_kernel_mbr_partuuid_support(d) else '${SYSLINUX_FIXED_ROOT}'}"
>>  SYSLINUX_TIMEOUT ?= "10"
>>
>>  inherit syslinux
>> @@ -98,6 +100,10 @@ build_boot_dd() {
>>       parted $IMAGE set 1 boot on
>>       parted $IMAGE print
>>
>> +     # Disk signature generated by parted isn't really random, so use our own generated signature
>> +     echo -ne "$(echo ${DISK_SIGNATURE} | fold -w 2 | tac | paste -sd '' | sed 's/\(..\)/\\x&/g')" | \
>> +             dd of=$IMAGE bs=1 seek=440 conv=notrunc
>
> Oi! So, can "fold -w 2 | tac | paste -sd '' be replaced with "rev" from
> the standard util-linux package?

The rev command doesn't handle binary data correctly:
$ echo -ne '\xb8\xe1\x0e\x5d' | rev
rev: stdin: Invalid or incomplete multibyte or wide character

>
> And the sed command... just insert "\x" every two characters? That
> doesn't seem to add any more randomness.... maybe I'm missing the point
> here?

That's to convert hex string to binary data by adding \x before each
pair of hex digits and passing to echo -ne.

>
>
>> +
>>       OFFSET=`expr $END2 / 512`
>>       dd if=${STAGING_DATADIR}/syslinux/mbr.bin of=$IMAGE conv=notrunc
>>       dd if=$HDDIMG of=$IMAGE conv=notrunc seek=1 bs=512
>> @@ -113,4 +119,26 @@ python do_bootdirectdisk() {
>>      bb.build.exec_func('build_boot_dd', d)
>>  }
>>
>> +def generate_disk_signature():
>> +    import uuid
>> +    return str(uuid.uuid4())[:8]
>> +
>> +def get_kernel_version(d):
>> +    import subprocess
>> +    version_cmd = r"grep '^VERSION\s*=' '%s/Makefile' | grep -o '[0-9]*$'" % (d.getVar("STAGING_KERNEL_DIR", True))
>> +    version = int(subprocess.Popen(version_cmd, shell=True, stdout=subprocess.PIPE).communicate()[0])
>> +    patchlevel_cmd = r"grep '^PATCHLEVEL\s*=' '%s/Makefile' | grep -o '[0-9]*$'" % (d.getVar("STAGING_KERNEL_DIR", True))
>> +    patchlevel = int(subprocess.Popen(patchlevel_cmd, shell=True, stdout=subprocess.PIPE).communicate()[0])
>> +    return (version, patchlevel)
>> +
>> +def has_kernel_config_option(option, d):
>> +    import subprocess
>> +    grep_cmd = r"grep '^CONFIG_%s=y$' '%s/.config'" % (option, d.getVar("STAGING_KERNEL_DIR", True))
>> +    return subprocess.call(grep_cmd, shell=True, stdout=subprocess.PIPE) == 0
>
> Is there a specific kernel option to test for the MBR disk signature
> support or is that inherent in the block drivers now? It would be nice
> if we could skip the kernel version check, that code looks dangerously
> fragile (no fault of yours).

I have submitted a new patch that is simpler and more flexible. It
does not rely on kernel checks.
This patch is no longer relevant now.

>
>> +
>> +def has_kernel_mbr_partuuid_support(d):
>> +    return get_kernel_version(d) >= (3, 8) and has_kernel_config_option("BLOCK", d)
>> +
>> +DISK_SIGNATURE := "${@generate_disk_signature()}"
>> +
>>  addtask bootdirectdisk before do_build
>
> --
> Darren Hart
> Intel Open Source Technology Center
> Yocto Project - Technical Lead - Linux Kernel
>

Regards,
Jonathan



More information about the Openembedded-core mailing list