x86/efi: Add efi_fake_mem support for EFI_MEMORY_SP
[linux-2.6-block.git] / arch / x86 / boot / compressed / kaslr.c
index 2e53c056ba20c16eda669d304e0da61346f56970..da0eedd5635d3bb3c95ac069c06e2ddad629cb33 100644 (file)
@@ -132,8 +132,14 @@ char *skip_spaces(const char *str)
 #include "../../../../lib/ctype.c"
 #include "../../../../lib/cmdline.c"
 
+enum parse_mode {
+       PARSE_MEMMAP,
+       PARSE_EFI,
+};
+
 static int
-parse_memmap(char *p, unsigned long long *start, unsigned long long *size)
+parse_memmap(char *p, unsigned long long *start, unsigned long long *size,
+               enum parse_mode mode)
 {
        char *oldp;
 
@@ -156,8 +162,29 @@ parse_memmap(char *p, unsigned long long *start, unsigned long long *size)
                *start = memparse(p + 1, &p);
                return 0;
        case '@':
-               /* memmap=nn@ss specifies usable region, should be skipped */
-               *size = 0;
+               if (mode == PARSE_MEMMAP) {
+                       /*
+                        * memmap=nn@ss specifies usable region, should
+                        * be skipped
+                        */
+                       *size = 0;
+               } else {
+                       unsigned long long flags;
+
+                       /*
+                        * efi_fake_mem=nn@ss:attr the attr specifies
+                        * flags that might imply a soft-reservation.
+                        */
+                       *start = memparse(p + 1, &p);
+                       if (p && *p == ':') {
+                               p++;
+                               if (kstrtoull(p, 0, &flags) < 0)
+                                       *size = 0;
+                               else if (flags & EFI_MEMORY_SP)
+                                       return 0;
+                       }
+                       *size = 0;
+               }
                /* Fall through */
        default:
                /*
@@ -172,7 +199,7 @@ parse_memmap(char *p, unsigned long long *start, unsigned long long *size)
        return -EINVAL;
 }
 
-static void mem_avoid_memmap(char *str)
+static void mem_avoid_memmap(enum parse_mode mode, char *str)
 {
        static int i;
 
@@ -187,7 +214,7 @@ static void mem_avoid_memmap(char *str)
                if (k)
                        *k++ = 0;
 
-               rc = parse_memmap(str, &start, &size);
+               rc = parse_memmap(str, &start, &size, mode);
                if (rc < 0)
                        break;
                str = k;
@@ -238,7 +265,6 @@ static void parse_gb_huge_pages(char *param, char *val)
        }
 }
 
-
 static void handle_mem_options(void)
 {
        char *args = (char *)get_cmd_line_ptr();
@@ -271,7 +297,7 @@ static void handle_mem_options(void)
                }
 
                if (!strcmp(param, "memmap")) {
-                       mem_avoid_memmap(val);
+                       mem_avoid_memmap(PARSE_MEMMAP, val);
                } else if (strstr(param, "hugepages")) {
                        parse_gb_huge_pages(param, val);
                } else if (!strcmp(param, "mem")) {
@@ -284,6 +310,8 @@ static void handle_mem_options(void)
                                goto out;
 
                        mem_limit = mem_size;
+               } else if (!strcmp(param, "efi_fake_mem")) {
+                       mem_avoid_memmap(PARSE_EFI, val);
                }
        }
 
@@ -760,6 +788,10 @@ process_efi_entries(unsigned long minimum, unsigned long image_size)
                if (md->type != EFI_CONVENTIONAL_MEMORY)
                        continue;
 
+               if (efi_soft_reserve_enabled() &&
+                   (md->attribute & EFI_MEMORY_SP))
+                       continue;
+
                if (efi_mirror_found &&
                    !(md->attribute & EFI_MEMORY_MORE_RELIABLE))
                        continue;