x86/boot: Add setup_indirect support in early_memremap_is_setup_data()
[sfrench/cifs-2.6.git] / arch / x86 / mm / ioremap.c
index ab666c4cd357b037c2b6e120e933e7facd85f94d..17a492c27306990c2d2d4ed3b0224152ffa2651e 100644 (file)
@@ -676,22 +676,51 @@ static bool memremap_is_setup_data(resource_size_t phys_addr,
 static bool __init early_memremap_is_setup_data(resource_size_t phys_addr,
                                                unsigned long size)
 {
+       struct setup_indirect *indirect;
        struct setup_data *data;
        u64 paddr, paddr_next;
 
        paddr = boot_params.hdr.setup_data;
        while (paddr) {
-               unsigned int len;
+               unsigned int len, size;
 
                if (phys_addr == paddr)
                        return true;
 
                data = early_memremap_decrypted(paddr, sizeof(*data));
+               if (!data) {
+                       pr_warn("failed to early memremap setup_data entry\n");
+                       return false;
+               }
+
+               size = sizeof(*data);
 
                paddr_next = data->next;
                len = data->len;
 
-               early_memunmap(data, sizeof(*data));
+               if ((phys_addr > paddr) && (phys_addr < (paddr + len))) {
+                       early_memunmap(data, sizeof(*data));
+                       return true;
+               }
+
+               if (data->type == SETUP_INDIRECT) {
+                       size += len;
+                       early_memunmap(data, sizeof(*data));
+                       data = early_memremap_decrypted(paddr, size);
+                       if (!data) {
+                               pr_warn("failed to early memremap indirect setup_data\n");
+                               return false;
+                       }
+
+                       indirect = (struct setup_indirect *)data->data;
+
+                       if (indirect->type != SETUP_INDIRECT) {
+                               paddr = indirect->addr;
+                               len = indirect->len;
+                       }
+               }
+
+               early_memunmap(data, size);
 
                if ((phys_addr > paddr) && (phys_addr < (paddr + len)))
                        return true;