@@ -163,6 +163,36 @@ static void __init process_memory_node(const void *fdt, int node,
}
}
+static bool __init check_xsm_signature(const void *fdt, int node,
+ const char *name,
+ u32 address_cells, u32 size_cells)
+{
+ uint32_t selinux_magic = 0xf97cff8c;
+ const struct fdt_property *prop;
+ paddr_t start, size;
+ const __be32 *cell;
+ /* 16 == sizeof(uint32_t) * 2 + sizeof("XenFlask") - 1 */
+ char magic[16];
+ int len;
+
+ prop = fdt_get_property(fdt, node, "reg", &len);
+ if ( !prop )
+ panic("node %s missing `reg' property\n", name);
+
+ if ( len < dt_cells_to_size(address_cells + size_cells) )
+ panic("fdt: node `%s': `reg` property length is too short\n", name);
+
+ cell = (const __be32 *)prop->data;
+ device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
+
+ copy_from_paddr(magic, start, 16);
+ if (strncmp(magic, (char *) &selinux_magic, sizeof(uint32_t)) ||
+ strncmp(magic + sizeof(uint32_t) * 2, "XenFlask", 8))
+ return 0;
+
+ return 1;
+}
+
static void __init process_multiboot_node(const void *fdt, int node,
const char *name,
u32 address_cells, u32 size_cells)
@@ -186,7 +216,13 @@ static void __init process_multiboot_node(const void *fdt, int node,
else
kind = BOOTMOD_UNKNOWN;
- /* Guess that first two unknown are kernel and ramdisk respectively. */
+ /**
+ * Guess the kind of these first two unknown respectively:
+ * (1) The first unknown must be kernel;
+ * (2) The second unknown is ramdisk, only if we have ramdisk;
+ * (3) Start from the 2nd unknown, detect the XSM binary signature;
+ * (4) If we got XSM in the 2nd unknown, that means we have not initrd.
+ */
if ( kind == BOOTMOD_UNKNOWN )
{
switch ( kind_guess++ )
@@ -195,6 +231,9 @@ static void __init process_multiboot_node(const void *fdt, int node,
case 1: kind = BOOTMOD_RAMDISK; break;
default: break;
}
+ if (kind_guess > 1 && check_xsm_signature(fdt, node, name,
+ address_cells, size_cells))
+ kind = BOOTMOD_XSM;
}
prop = fdt_get_property(fdt, node, "reg", &len);