]>
git.ipfire.org Git - people/ms/u-boot.git/blob - cmd/efi.c
2 * (C) Copyright 2015 Google, Inc
3 * Written by Simon Glass <sjg@chromium.org>
5 * SPDX-License-Identifier: GPL-2.0+
14 static const char *const type_name
[] = {
31 static struct attr_info
{
35 { EFI_MEMORY_UC_SHIFT
, "uncached" },
36 { EFI_MEMORY_WC_SHIFT
, "write-coalescing" },
37 { EFI_MEMORY_WT_SHIFT
, "write-through" },
38 { EFI_MEMORY_WB_SHIFT
, "write-back" },
39 { EFI_MEMORY_UCE_SHIFT
, "uncached & exported" },
40 { EFI_MEMORY_WP_SHIFT
, "write-protect" },
41 { EFI_MEMORY_RP_SHIFT
, "read-protect" },
42 { EFI_MEMORY_XP_SHIFT
, "execute-protect" },
43 { EFI_MEMORY_RUNTIME_SHIFT
, "needs runtime mapping" }
46 /* Maximum different attribute values we can track */
47 #define ATTR_SEEN_MAX 30
49 static inline bool is_boot_services(int type
)
51 return type
== EFI_LOADER_CODE
|| type
== EFI_LOADER_DATA
||
52 type
== EFI_BOOT_SERVICES_CODE
||
53 type
== EFI_BOOT_SERVICES_DATA
;
56 static int h_cmp_entry(const void *v1
, const void *v2
)
58 const struct efi_mem_desc
*desc1
= v1
;
59 const struct efi_mem_desc
*desc2
= v2
;
60 int64_t diff
= desc1
->physical_start
- desc2
->physical_start
;
63 * Manually calculate the difference to avoid sign loss in the 64-bit
64 * to 32-bit conversion
66 return diff
< 0 ? -1 : diff
> 0 ? 1 : 0;
69 void *efi_build_mem_table(struct efi_entry_memmap
*map
, int size
, bool skip_bs
)
71 struct efi_mem_desc
*desc
, *end
, *base
, *dest
, *prev
;
75 base
= malloc(size
+ sizeof(*desc
));
77 debug("%s: Cannot allocate %#x bytes\n", __func__
, size
);
80 end
= (struct efi_mem_desc
*)((ulong
)map
+ size
);
81 count
= ((ulong
)end
- (ulong
)map
->desc
) / map
->desc_size
;
82 memcpy(base
, map
->desc
, (ulong
)end
- (ulong
)map
->desc
);
83 qsort(base
, count
, map
->desc_size
, h_cmp_entry
);
88 for (desc
= base
; desc
< end
; desc
= efi_get_next_mem_desc(map
, desc
)) {
90 int type
= desc
->type
;
92 if (skip_bs
&& is_boot_services(desc
->type
))
93 type
= EFI_CONVENTIONAL_MEMORY
;
95 memcpy(dest
, desc
, map
->desc_size
);
97 if (!skip_bs
|| !prev
)
99 else if (desc
->physical_start
!= addr
)
101 else if (type
!= EFI_CONVENTIONAL_MEMORY
)
103 else if (prev
->type
!= EFI_CONVENTIONAL_MEMORY
)
107 prev
->num_pages
+= desc
->num_pages
;
110 dest
= efi_get_next_mem_desc(map
, dest
);
112 addr
= desc
->physical_start
+ (desc
->num_pages
<<
117 dest
->type
= EFI_TABLE_END
;
122 static void efi_print_mem_table(struct efi_entry_memmap
*map
,
123 struct efi_mem_desc
*desc
, bool skip_bs
)
125 u64 attr_seen
[ATTR_SEEN_MAX
];
130 printf(" # %-14s %10s %10s %10s %s\n", "Type", "Physical",
131 "Virtual", "Size", "Attributes");
133 /* Keep track of all the different attributes we have seen */
136 for (upto
= 0; desc
->type
!= EFI_TABLE_END
;
137 upto
++, desc
= efi_get_next_mem_desc(map
, desc
)) {
141 if (skip_bs
&& is_boot_services(desc
->type
))
143 if (desc
->physical_start
!= addr
) {
144 printf(" %-14s %010llx %10s %010llx\n", "<gap>",
145 addr
, "", desc
->physical_start
- addr
);
147 size
= desc
->num_pages
<< EFI_PAGE_SHIFT
;
149 name
= desc
->type
< ARRAY_SIZE(type_name
) ?
150 type_name
[desc
->type
] : "<invalid>";
151 printf("%2d %x:%-12s %010llx %010llx %010llx ", upto
,
152 desc
->type
, name
, desc
->physical_start
,
153 desc
->virtual_start
, size
);
154 if (desc
->attribute
& EFI_MEMORY_RUNTIME
)
156 printf("%llx", desc
->attribute
& ~EFI_MEMORY_RUNTIME
);
159 for (i
= 0; i
< attr_seen_count
; i
++) {
160 if (attr_seen
[i
] == desc
->attribute
)
163 if (i
== attr_seen_count
&& i
< ATTR_SEEN_MAX
)
164 attr_seen
[attr_seen_count
++] = desc
->attribute
;
165 addr
= desc
->physical_start
+ size
;
168 printf("\nAttributes key:\n");
169 for (i
= 0; i
< attr_seen_count
; i
++) {
170 u64 attr
= attr_seen
[i
];
174 printf("%c%llx: ", attr
& EFI_MEMORY_RUNTIME
? 'r' : ' ',
175 attr
& ~EFI_MEMORY_RUNTIME
);
176 for (j
= 0, first
= true; j
< ARRAY_SIZE(mem_attr
); j
++) {
177 if (attr
& (1ULL << mem_attr
[j
].shift
)) {
182 printf("%s", mem_attr
[j
].name
);
188 printf("*Some areas are merged (use 'all' to see)\n");
191 static int do_efi_mem(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
193 struct efi_mem_desc
*desc
;
194 struct efi_entry_memmap
*map
;
198 skip_bs
= !argc
|| *argv
[0] != 'a';
199 ret
= efi_info_get(EFIET_MEMORY_MAP
, (void **)&map
, &size
);
202 printf("No EFI table available\n");
204 case -EPROTONOSUPPORT
:
205 printf("Incorrect EFI table version\n");
208 printf("EFI table at %lx, memory map %p, size %x, version %x, descr. size %#x\n",
209 gd
->arch
.table
, map
, size
, map
->version
, map
->desc_size
);
210 if (map
->version
!= EFI_MEM_DESC_VERSION
) {
211 printf("Incorrect memory map version\n");
212 ret
= -EPROTONOSUPPORT
;
216 desc
= efi_build_mem_table(map
, size
, skip_bs
);
222 efi_print_mem_table(map
, desc
, skip_bs
);
226 printf("Error: %d\n", ret
);
228 return ret
? CMD_RET_FAILURE
: 0;
231 static cmd_tbl_t efi_commands
[] = {
232 U_BOOT_CMD_MKENT(mem
, 1, 1, do_efi_mem
, "", ""),
235 static int do_efi(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
241 return CMD_RET_USAGE
;
242 efi_cmd
= find_cmd_tbl(argv
[1], efi_commands
, ARRAY_SIZE(efi_commands
));
245 if (!efi_cmd
|| argc
> efi_cmd
->maxargs
)
246 return CMD_RET_USAGE
;
248 ret
= efi_cmd
->cmd(efi_cmd
, flag
, argc
, argv
);
250 return cmd_process_error(efi_cmd
, ret
);
256 "mem [all] Dump memory information [include boot services]"