forked from Minki/linux
bootconfig: Add bootconfig magic word for indicating bootconfig explicitly
Add bootconfig magic word to the end of bootconfig on initrd image for indicating explicitly the bootconfig is there. Also tools/bootconfig treats wrong size or wrong checksum or parse error as an error, because if there is a bootconfig magic word, there must be a bootconfig. The bootconfig magic word is "#BOOTCONFIG\n", 12 bytes word. Thus the block image of the initrd file with bootconfig is as follows. [Initrd][bootconfig][size][csum][#BOOTCONFIG\n] Link: http://lkml.kernel.org/r/158220112263.26565.3944814205960612841.stgit@devnote2 Suggested-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
parent
d8a953ddde
commit
85c46b78da
@ -102,9 +102,13 @@ Boot Kernel With a Boot Config
|
|||||||
==============================
|
==============================
|
||||||
|
|
||||||
Since the boot configuration file is loaded with initrd, it will be added
|
Since the boot configuration file is loaded with initrd, it will be added
|
||||||
to the end of the initrd (initramfs) image file. The Linux kernel decodes
|
to the end of the initrd (initramfs) image file with size, checksum and
|
||||||
the last part of the initrd image in memory to get the boot configuration
|
12-byte magic word as below.
|
||||||
data.
|
|
||||||
|
[initrd][bootconfig][size(u32)][checksum(u32)][#BOOTCONFIG\n]
|
||||||
|
|
||||||
|
The Linux kernel decodes the last part of the initrd image in memory to
|
||||||
|
get the boot configuration data.
|
||||||
Because of this "piggyback" method, there is no need to change or
|
Because of this "piggyback" method, there is no need to change or
|
||||||
update the boot loader and the kernel image itself.
|
update the boot loader and the kernel image itself.
|
||||||
|
|
||||||
|
@ -10,6 +10,9 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define BOOTCONFIG_MAGIC "#BOOTCONFIG\n"
|
||||||
|
#define BOOTCONFIG_MAGIC_LEN 12
|
||||||
|
|
||||||
/* XBC tree node */
|
/* XBC tree node */
|
||||||
struct xbc_node {
|
struct xbc_node {
|
||||||
u16 next;
|
u16 next;
|
||||||
|
@ -1222,7 +1222,7 @@ config BOOT_CONFIG
|
|||||||
Extra boot config allows system admin to pass a config file as
|
Extra boot config allows system admin to pass a config file as
|
||||||
complemental extension of kernel cmdline when booting.
|
complemental extension of kernel cmdline when booting.
|
||||||
The boot config file must be attached at the end of initramfs
|
The boot config file must be attached at the end of initramfs
|
||||||
with checksum and size.
|
with checksum, size and magic word.
|
||||||
See <file:Documentation/admin-guide/bootconfig.rst> for details.
|
See <file:Documentation/admin-guide/bootconfig.rst> for details.
|
||||||
|
|
||||||
If unsure, say Y.
|
If unsure, say Y.
|
||||||
|
@ -374,7 +374,11 @@ static void __init setup_boot_config(const char *cmdline)
|
|||||||
if (!initrd_end)
|
if (!initrd_end)
|
||||||
goto not_found;
|
goto not_found;
|
||||||
|
|
||||||
hdr = (u32 *)(initrd_end - 8);
|
data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN;
|
||||||
|
if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN))
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
hdr = (u32 *)(data - 8);
|
||||||
size = hdr[0];
|
size = hdr[0];
|
||||||
csum = hdr[1];
|
csum = hdr[1];
|
||||||
|
|
||||||
|
@ -131,15 +131,26 @@ int load_xbc_from_initrd(int fd, char **buf)
|
|||||||
struct stat stat;
|
struct stat stat;
|
||||||
int ret;
|
int ret;
|
||||||
u32 size = 0, csum = 0, rcsum;
|
u32 size = 0, csum = 0, rcsum;
|
||||||
|
char magic[BOOTCONFIG_MAGIC_LEN];
|
||||||
|
|
||||||
ret = fstat(fd, &stat);
|
ret = fstat(fd, &stat);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if (stat.st_size < 8)
|
if (stat.st_size < 8 + BOOTCONFIG_MAGIC_LEN)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (lseek(fd, -8, SEEK_END) < 0) {
|
if (lseek(fd, -BOOTCONFIG_MAGIC_LEN, SEEK_END) < 0) {
|
||||||
|
pr_err("Failed to lseek: %d\n", -errno);
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
if (read(fd, magic, BOOTCONFIG_MAGIC_LEN) < 0)
|
||||||
|
return -errno;
|
||||||
|
/* Check the bootconfig magic bytes */
|
||||||
|
if (memcmp(magic, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (lseek(fd, -(8 + BOOTCONFIG_MAGIC_LEN), SEEK_END) < 0) {
|
||||||
pr_err("Failed to lseek: %d\n", -errno);
|
pr_err("Failed to lseek: %d\n", -errno);
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
@ -150,11 +161,14 @@ int load_xbc_from_initrd(int fd, char **buf)
|
|||||||
if (read(fd, &csum, sizeof(u32)) < 0)
|
if (read(fd, &csum, sizeof(u32)) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
/* Wrong size, maybe no boot config here */
|
/* Wrong size error */
|
||||||
if (stat.st_size < size + 8)
|
if (stat.st_size < size + 8 + BOOTCONFIG_MAGIC_LEN) {
|
||||||
return 0;
|
pr_err("bootconfig size is too big\n");
|
||||||
|
return -E2BIG;
|
||||||
|
}
|
||||||
|
|
||||||
if (lseek(fd, stat.st_size - 8 - size, SEEK_SET) < 0) {
|
if (lseek(fd, stat.st_size - (size + 8 + BOOTCONFIG_MAGIC_LEN),
|
||||||
|
SEEK_SET) < 0) {
|
||||||
pr_err("Failed to lseek: %d\n", -errno);
|
pr_err("Failed to lseek: %d\n", -errno);
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
@ -163,17 +177,17 @@ int load_xbc_from_initrd(int fd, char **buf)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Wrong Checksum, maybe no boot config here */
|
/* Wrong Checksum */
|
||||||
rcsum = checksum((unsigned char *)*buf, size);
|
rcsum = checksum((unsigned char *)*buf, size);
|
||||||
if (csum != rcsum) {
|
if (csum != rcsum) {
|
||||||
pr_err("checksum error: %d != %d\n", csum, rcsum);
|
pr_err("checksum error: %d != %d\n", csum, rcsum);
|
||||||
return 0;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = xbc_init(*buf);
|
ret = xbc_init(*buf);
|
||||||
/* Wrong data, maybe no boot config here */
|
/* Wrong data */
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return 0;
|
return ret;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -226,7 +240,8 @@ int delete_xbc(const char *path)
|
|||||||
} else if (size > 0) {
|
} else if (size > 0) {
|
||||||
ret = fstat(fd, &stat);
|
ret = fstat(fd, &stat);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = ftruncate(fd, stat.st_size - size - 8);
|
ret = ftruncate(fd, stat.st_size
|
||||||
|
- size - 8 - BOOTCONFIG_MAGIC_LEN);
|
||||||
if (ret)
|
if (ret)
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
} /* Ignore if there is no boot config in initrd */
|
} /* Ignore if there is no boot config in initrd */
|
||||||
@ -295,6 +310,12 @@ int apply_xbc(const char *path, const char *xbc_path)
|
|||||||
pr_err("Failed to apply a boot config: %d\n", ret);
|
pr_err("Failed to apply a boot config: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
/* Write a magic word of the bootconfig */
|
||||||
|
ret = write(fd, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("Failed to apply a boot config magic: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ xpass $BOOTCONF -a $TEMPCONF $INITRD
|
|||||||
new_size=$(stat -c %s $INITRD)
|
new_size=$(stat -c %s $INITRD)
|
||||||
|
|
||||||
echo "File size check"
|
echo "File size check"
|
||||||
xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9)
|
xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9 + 12)
|
||||||
|
|
||||||
echo "Apply command repeat test"
|
echo "Apply command repeat test"
|
||||||
xpass $BOOTCONF -a $TEMPCONF $INITRD
|
xpass $BOOTCONF -a $TEMPCONF $INITRD
|
||||||
|
Loading…
Reference in New Issue
Block a user