]>
git.ipfire.org Git - thirdparty/u-boot.git/blob - cmd/efi.c
1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
15 static const char *const type_name
[] = {
32 static struct attr_info
{
36 { EFI_MEMORY_UC
, "uncached" },
37 { EFI_MEMORY_WC
, "write-coalescing" },
38 { EFI_MEMORY_WT
, "write-through" },
39 { EFI_MEMORY_WB
, "write-back" },
40 { EFI_MEMORY_UCE
, "uncached & exported" },
41 { EFI_MEMORY_WP
, "write-protect" },
42 { EFI_MEMORY_RP
, "read-protect" },
43 { EFI_MEMORY_XP
, "execute-protect" },
44 { EFI_MEMORY_NV
, "non-volatile" },
45 { EFI_MEMORY_MORE_RELIABLE
, "higher reliability" },
46 { EFI_MEMORY_RO
, "read-only" },
47 { EFI_MEMORY_SP
, "specific purpose" },
48 { EFI_MEMORY_RUNTIME
, "needs runtime mapping" }
51 /* Maximum different attribute values we can track */
52 #define ATTR_SEEN_MAX 30
54 static inline bool is_boot_services(int type
)
56 return type
== EFI_LOADER_CODE
|| type
== EFI_LOADER_DATA
||
57 type
== EFI_BOOT_SERVICES_CODE
||
58 type
== EFI_BOOT_SERVICES_DATA
;
61 static int h_cmp_entry(const void *v1
, const void *v2
)
63 const struct efi_mem_desc
*desc1
= v1
;
64 const struct efi_mem_desc
*desc2
= v2
;
65 int64_t diff
= desc1
->physical_start
- desc2
->physical_start
;
68 * Manually calculate the difference to avoid sign loss in the 64-bit
69 * to 32-bit conversion
71 return diff
< 0 ? -1 : diff
> 0 ? 1 : 0;
74 void *efi_build_mem_table(struct efi_entry_memmap
*map
, int size
, bool skip_bs
)
76 struct efi_mem_desc
*desc
, *end
, *base
, *dest
, *prev
;
80 base
= malloc(size
+ sizeof(*desc
));
82 debug("%s: Cannot allocate %#x bytes\n", __func__
, size
);
85 end
= (struct efi_mem_desc
*)((ulong
)map
+ size
);
86 count
= ((ulong
)end
- (ulong
)map
->desc
) / map
->desc_size
;
87 memcpy(base
, map
->desc
, (ulong
)end
- (ulong
)map
->desc
);
88 qsort(base
, count
, map
->desc_size
, h_cmp_entry
);
92 end
= (struct efi_mem_desc
*)((ulong
)base
+ count
* map
->desc_size
);
93 for (desc
= base
; desc
< end
; desc
= efi_get_next_mem_desc(map
, desc
)) {
95 int type
= desc
->type
;
97 if (skip_bs
&& is_boot_services(desc
->type
))
98 type
= EFI_CONVENTIONAL_MEMORY
;
100 memcpy(dest
, desc
, map
->desc_size
);
102 if (!skip_bs
|| !prev
)
104 else if (desc
->physical_start
!= addr
)
106 else if (type
!= EFI_CONVENTIONAL_MEMORY
)
108 else if (prev
->type
!= EFI_CONVENTIONAL_MEMORY
)
112 prev
->num_pages
+= desc
->num_pages
;
115 dest
= efi_get_next_mem_desc(map
, dest
);
117 addr
= desc
->physical_start
+ (desc
->num_pages
<<
122 dest
->type
= EFI_TABLE_END
;
127 static void efi_print_mem_table(struct efi_entry_memmap
*map
,
128 struct efi_mem_desc
*desc
, bool skip_bs
)
130 u64 attr_seen
[ATTR_SEEN_MAX
];
135 printf(" # %-14s %10s %10s %10s %s\n", "Type", "Physical",
136 "Virtual", "Size", "Attributes");
138 /* Keep track of all the different attributes we have seen */
141 for (upto
= 0; desc
->type
!= EFI_TABLE_END
;
142 upto
++, desc
= efi_get_next_mem_desc(map
, desc
)) {
146 if (skip_bs
&& is_boot_services(desc
->type
))
148 if (desc
->physical_start
!= addr
) {
149 printf(" %-14s %010llx %10s %010llx\n", "<gap>",
150 addr
, "", desc
->physical_start
- addr
);
152 size
= desc
->num_pages
<< EFI_PAGE_SHIFT
;
154 name
= desc
->type
< ARRAY_SIZE(type_name
) ?
155 type_name
[desc
->type
] : "<invalid>";
156 printf("%2d %x:%-12s %010llx %010llx %010llx ", upto
,
157 desc
->type
, name
, desc
->physical_start
,
158 desc
->virtual_start
, size
);
159 if (desc
->attribute
& EFI_MEMORY_RUNTIME
)
161 printf("%llx", desc
->attribute
& ~EFI_MEMORY_RUNTIME
);
164 for (i
= 0; i
< attr_seen_count
; i
++) {
165 if (attr_seen
[i
] == desc
->attribute
)
168 if (i
== attr_seen_count
&& i
< ATTR_SEEN_MAX
)
169 attr_seen
[attr_seen_count
++] = desc
->attribute
;
170 addr
= desc
->physical_start
+ size
;
173 printf("\nAttributes key:\n");
174 for (i
= 0; i
< attr_seen_count
; i
++) {
175 u64 attr
= attr_seen
[i
];
179 printf("%c%llx: ", (attr
& EFI_MEMORY_RUNTIME
) ? 'r' : ' ',
180 attr
& ~EFI_MEMORY_RUNTIME
);
181 for (j
= 0, first
= true; j
< ARRAY_SIZE(mem_attr
); j
++) {
182 if (attr
& mem_attr
[j
].val
) {
187 printf("%s", mem_attr
[j
].name
);
193 printf("*Some areas are merged (use 'all' to see)\n");
196 static int do_efi_mem(struct cmd_tbl
*cmdtp
, int flag
, int argc
,
199 struct efi_mem_desc
*desc
;
200 struct efi_entry_memmap
*map
;
204 skip_bs
= !argc
|| *argv
[0] != 'a';
205 ret
= efi_info_get(EFIET_MEMORY_MAP
, (void **)&map
, &size
);
208 printf("No EFI table available\n");
210 case -EPROTONOSUPPORT
:
211 printf("Incorrect EFI table version\n");
214 printf("EFI table at %lx, memory map %p, size %x, version %x, descr. size %#x\n",
215 gd
->arch
.table
, map
, size
, map
->version
, map
->desc_size
);
216 if (map
->version
!= EFI_MEM_DESC_VERSION
) {
217 printf("Incorrect memory map version\n");
218 ret
= -EPROTONOSUPPORT
;
222 desc
= efi_build_mem_table(map
, size
, skip_bs
);
228 efi_print_mem_table(map
, desc
, skip_bs
);
232 printf("Error: %d\n", ret
);
234 return ret
? CMD_RET_FAILURE
: 0;
237 static struct cmd_tbl efi_commands
[] = {
238 U_BOOT_CMD_MKENT(mem
, 1, 1, do_efi_mem
, "", ""),
241 static int do_efi(struct cmd_tbl
*cmdtp
, int flag
, int argc
, char *const argv
[])
243 struct cmd_tbl
*efi_cmd
;
247 return CMD_RET_USAGE
;
248 efi_cmd
= find_cmd_tbl(argv
[1], efi_commands
, ARRAY_SIZE(efi_commands
));
251 if (!efi_cmd
|| argc
> efi_cmd
->maxargs
)
252 return CMD_RET_USAGE
;
254 ret
= efi_cmd
->cmd(efi_cmd
, flag
, argc
, argv
);
256 return cmd_process_error(efi_cmd
, ret
);
262 "mem [all] Dump memory information [include boot services]"