#include <errno.h>
#include <linux/list.h>
+#ifdef CONFIG_DM_RNG
+#include <dm.h>
+#include <rng.h>
+#endif
+
#include <splash.h>
#include <asm/io.h>
#define MAX_TFTP_PATH_LEN 512
+int pxe_get_file_size(ulong *sizep)
+{
+ const char *val;
+
+ val = from_env("filesize");
+ if (!val)
+ return -ENOENT;
+
+ if (strict_strtoul(val, 16, sizep) < 0)
+ return -EINVAL;
+
+ return 0;
+}
+
/**
* format_mac_pxe() - obtain a MAC address in the PXE format
*
*
* @outbuf: Buffer to write string to
* @outbuf_len: length of buffer
- * @return 1 if OK, -ENOSPC if buffer is too small, -ENOENT is there is no
+ * Return: 1 if OK, -ENOSPC if buffer is too small, -ENOENT is there is no
* current ethernet device
*/
int format_mac_pxe(char *outbuf, size_t outbuf_len)
* @ctx: PXE context
* @file_path: File path to read (relative to the PXE file)
* @file_addr: Address to load file to
+ * @filesizep: If not NULL, returns the file size in bytes
* Returns 1 for success, or < 0 on error
*/
static int get_relfile(struct pxe_context *ctx, const char *file_path,
- unsigned long file_addr)
+ unsigned long file_addr, ulong *filesizep)
{
size_t path_len;
char relfile[MAX_TFTP_PATH_LEN + 1];
char addr_buf[18];
+ ulong size;
+ int ret;
if (file_path[0] == '/' && ctx->allow_abs_path)
*relfile = '\0';
sprintf(addr_buf, "%lx", file_addr);
- return ctx->getfile(ctx, relfile, addr_buf);
+ ret = ctx->getfile(ctx, relfile, addr_buf, &size);
+ if (ret < 0)
+ return log_msg_ret("get", ret);
+ if (filesizep)
+ *filesizep = size;
+
+ return 1;
}
/**
* Returns 1 for success, or < 0 on error
*/
int get_pxe_file(struct pxe_context *ctx, const char *file_path,
- unsigned long file_addr)
+ ulong file_addr)
{
- unsigned long config_file_size;
- char *tftp_filesize;
+ ulong size;
int err;
char *buf;
- err = get_relfile(ctx, file_path, file_addr);
+ err = get_relfile(ctx, file_path, file_addr, &size);
if (err < 0)
return err;
- /*
- * the file comes without a NUL byte at the end, so find out its size
- * and add the NUL byte.
- */
- tftp_filesize = from_env("filesize");
- if (!tftp_filesize)
- return -ENOENT;
-
- if (strict_strtoul(tftp_filesize, 16, &config_file_size) < 0)
- return -EINVAL;
-
- buf = map_sysmem(file_addr + config_file_size, 1);
+ buf = map_sysmem(file_addr + size, 1);
*buf = '\0';
unmap_sysmem(buf);
* @file_path: File path to read (relative to the PXE file)
* @envaddr_name: Name of environment variable which contains the address to
* load to
+ * @filesizep: Returns the file size in bytes
* Returns 1 on success, -ENOENT if @envaddr_name does not exist as an
* environment variable, -EINVAL if its format is not valid hex, or other
* value < 0 on other error
*/
static int get_relfile_envaddr(struct pxe_context *ctx, const char *file_path,
- const char *envaddr_name)
+ const char *envaddr_name, ulong *filesizep)
{
unsigned long file_addr;
char *envaddr;
if (strict_strtoul(envaddr, 16, &file_addr) < 0)
return -EINVAL;
- return get_relfile(ctx, file_path, file_addr);
+ return get_relfile(ctx, file_path, file_addr, filesizep);
}
/**
return run_command_list(localcmd, strlen(localcmd), 0);
}
+/*
+ * label_boot_kaslrseed generate kaslrseed from hw rng
+ */
+
+static void label_boot_kaslrseed(void)
+{
+#ifdef CONFIG_DM_RNG
+ ulong fdt_addr;
+ struct fdt_header *working_fdt;
+ size_t n = 0x8;
+ struct udevice *dev;
+ u64 *buf;
+ int nodeoffset;
+ int err;
+
+ /* Get the main fdt and map it */
+ fdt_addr = hextoul(env_get("fdt_addr_r"), NULL);
+ working_fdt = map_sysmem(fdt_addr, 0);
+ err = fdt_check_header(working_fdt);
+ if (err)
+ return;
+
+ /* add extra size for holding kaslr-seed */
+ /* err is new fdt size, 0 or negtive */
+ err = fdt_shrink_to_minimum(working_fdt, 512);
+ if (err <= 0)
+ return;
+
+ if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
+ printf("No RNG device\n");
+ return;
+ }
+
+ nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
+ if (nodeoffset < 0) {
+ printf("Reading chosen node failed\n");
+ return;
+ }
+
+ buf = malloc(n);
+ if (!buf) {
+ printf("Out of memory\n");
+ return;
+ }
+
+ if (dm_rng_read(dev, buf, n)) {
+ printf("Reading RNG failed\n");
+ goto err;
+ }
+
+ err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
+ if (err < 0) {
+ printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
+ goto err;
+ }
+err:
+ free(buf);
+#endif
+ return;
+}
+
/**
* label_boot_fdtoverlay() - Loads fdt overlays specified in 'fdtoverlays'
*
goto skip_overlay;
/* Load overlay file */
- err = get_relfile_envaddr(ctx, overlayfile,
- "fdtoverlay_addr_r");
+ err = get_relfile_envaddr(ctx, overlayfile, "fdtoverlay_addr_r",
+ NULL);
if (err < 0) {
printf("Failed loading overlay %s\n", overlayfile);
goto skip_overlay;
}
if (label->initrd) {
- if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r") < 0) {
+ ulong size;
+
+ if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r",
+ &size) < 0) {
printf("Skipping %s for failure retrieving initrd\n",
label->name);
return 1;
}
initrd_addr_str = env_get("ramdisk_addr_r");
- strncpy(initrd_filesize, env_get("filesize"), 9);
+ strcpy(initrd_filesize, simple_xtoa(size));
strncpy(initrd_str, initrd_addr_str, 18);
strcat(initrd_str, ":");
strncat(initrd_str, initrd_filesize, 9);
}
- if (get_relfile_envaddr(ctx, label->kernel, "kernel_addr_r") < 0) {
+ if (get_relfile_envaddr(ctx, label->kernel, "kernel_addr_r",
+ NULL) < 0) {
printf("Skipping %s for failure retrieving kernel\n",
label->name);
return 1;
* Scenario 2: If there is an fdt_addr specified, pass it along to
* bootm, and adjust argc appropriately.
*
- * Scenario 3: fdt blob is not available.
+ * Scenario 3: If there is an fdtcontroladdr specified, pass it along to
+ * bootm, and adjust argc appropriately.
+ *
+ * Scenario 4: fdt blob is not available.
*/
bootm_argv[3] = env_get("fdt_addr_r");
if (fdtfile) {
int err = get_relfile_envaddr(ctx, fdtfile,
- "fdt_addr_r");
+ "fdt_addr_r", NULL);
free(fdtfilefree);
if (err < 0) {
}
}
+ if (label->kaslrseed)
+ label_boot_kaslrseed();
+
#ifdef CONFIG_OF_LIBFDT_OVERLAY
if (label->fdtoverlays)
label_boot_fdtoverlay(ctx, label);
if (!bootm_argv[3])
bootm_argv[3] = env_get("fdt_addr");
+ if (!bootm_argv[3])
+ bootm_argv[3] = env_get("fdtcontroladdr");
+
if (bootm_argv[3]) {
if (!bootm_argv[2])
bootm_argv[2] = "-";
T_ONTIMEOUT,
T_IPAPPEND,
T_BACKGROUND,
+ T_KASLRSEED,
T_INVALID
};
{"ontimeout", T_ONTIMEOUT,},
{"ipappend", T_IPAPPEND,},
{"background", T_BACKGROUND,},
+ {"kaslrseed", T_KASLRSEED,},
{NULL, T_INVALID}
};
err = parse_integer(c, &label->ipappend);
break;
+ case T_KASLRSEED:
+ label->kaslrseed = 1;
+ break;
+
case T_EOL:
break;
struct pxe_label *label;
struct list_head *pos;
struct menu *m;
+ char *label_override;
int err;
int i = 1;
char *default_num = NULL;
+ char *override_num = NULL;
/*
* Create a menu and add items for all the labels.
if (!m)
return NULL;
+ label_override = env_get("pxe_label_override");
+
list_for_each(pos, &cfg->labels) {
label = list_entry(pos, struct pxe_label, list);
if (cfg->default_label &&
(strcmp(label->name, cfg->default_label) == 0))
default_num = label->num;
+ if (label_override && !strcmp(label->name, label_override))
+ override_num = label->num;
+ }
+
+
+ if (label_override) {
+ if (override_num)
+ default_num = override_num;
+ else
+ printf("Missing override pxe label: %s\n",
+ label_override);
}
/*
if (IS_ENABLED(CONFIG_CMD_BMP)) {
/* display BMP if available */
if (cfg->bmp) {
- if (get_relfile(ctx, cfg->bmp, image_load_addr)) {
+ if (get_relfile(ctx, cfg->bmp, image_load_addr, NULL)) {
if (CONFIG_IS_ENABLED(CMD_CLS))
run_command("cls", 0);
bmp_display(image_load_addr,