binman: Tweak collect_contents_to_file() and docs
[platform/kernel/u-boot.git] / boot / pxe_utils.c
index a32acca..0c24bec 100644 (file)
 #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>
 
@@ -56,7 +61,7 @@ int pxe_get_file_size(ulong *sizep)
  *
  * @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)
@@ -311,6 +316,67 @@ static int label_localboot(struct pxe_label *label)
        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'
  *
@@ -631,6 +697,9 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
                                }
                        }
 
+               if (label->kaslrseed)
+                       label_boot_kaslrseed();
+
 #ifdef CONFIG_OF_LIBFDT_OVERLAY
                        if (label->fdtoverlays)
                                label_boot_fdtoverlay(ctx, label);
@@ -710,6 +779,7 @@ enum token_type {
        T_ONTIMEOUT,
        T_IPAPPEND,
        T_BACKGROUND,
+       T_KASLRSEED,
        T_INVALID
 };
 
@@ -741,6 +811,7 @@ static const struct token keywords[] = {
        {"ontimeout", T_ONTIMEOUT,},
        {"ipappend", T_IPAPPEND,},
        {"background", T_BACKGROUND,},
+       {"kaslrseed", T_KASLRSEED,},
        {NULL, T_INVALID}
 };
 
@@ -1194,6 +1265,10 @@ static int parse_label(char **c, struct pxe_menu *cfg)
                        err = parse_integer(c, &label->ipappend);
                        break;
 
+               case T_KASLRSEED:
+                       label->kaslrseed = 1;
+                       break;
+
                case T_EOL:
                        break;
 
@@ -1355,9 +1430,11 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)
        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.
@@ -1367,6 +1444,8 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)
        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);
 
@@ -1378,6 +1457,17 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)
                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);
        }
 
        /*