]>
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>
13 static const char *const type_name
[] = {
30 static struct attr_info
{
34 { EFI_MEMORY_UC
, "uncached" },
35 { EFI_MEMORY_WC
, "write-coalescing" },
36 { EFI_MEMORY_WT
, "write-through" },
37 { EFI_MEMORY_WB
, "write-back" },
38 { EFI_MEMORY_UCE
, "uncached & exported" },
39 { EFI_MEMORY_WP
, "write-protect" },
40 { EFI_MEMORY_RP
, "read-protect" },
41 { EFI_MEMORY_XP
, "execute-protect" },
42 { EFI_MEMORY_NV
, "non-volatile" },
43 { EFI_MEMORY_MORE_RELIABLE
, "higher reliability" },
44 { EFI_MEMORY_RO
, "read-only" },
45 { EFI_MEMORY_RUNTIME
, "needs runtime mapping" }
48 /* Maximum different attribute values we can track */
49 #define ATTR_SEEN_MAX 30
51 static inline bool is_boot_services(int type
)
53 return type
== EFI_LOADER_CODE
|| type
== EFI_LOADER_DATA
||
54 type
== EFI_BOOT_SERVICES_CODE
||
55 type
== EFI_BOOT_SERVICES_DATA
;
58 static int h_cmp_entry(const void *v1
, const void *v2
)
60 const struct efi_mem_desc
*desc1
= v1
;
61 const struct efi_mem_desc
*desc2
= v2
;
62 int64_t diff
= desc1
->physical_start
- desc2
->physical_start
;
65 * Manually calculate the difference to avoid sign loss in the 64-bit
66 * to 32-bit conversion
68 return diff
< 0 ? -1 : diff
> 0 ? 1 : 0;
71 void *efi_build_mem_table(struct efi_entry_memmap
*map
, int size
, bool skip_bs
)
73 struct efi_mem_desc
*desc
, *end
, *base
, *dest
, *prev
;
77 base
= malloc(size
+ sizeof(*desc
));
79 debug("%s: Cannot allocate %#x bytes\n", __func__
, size
);
82 end
= (struct efi_mem_desc
*)((ulong
)map
+ size
);
83 count
= ((ulong
)end
- (ulong
)map
->desc
) / map
->desc_size
;
84 memcpy(base
, map
->desc
, (ulong
)end
- (ulong
)map
->desc
);
85 qsort(base
, count
, map
->desc_size
, h_cmp_entry
);
89 end
= (struct efi_mem_desc
*)((ulong
)base
+ count
* map
->desc_size
);
90 for (desc
= base
; desc
< end
; desc
= efi_get_next_mem_desc(map
, desc
)) {
92 int type
= desc
->type
;
94 if (skip_bs
&& is_boot_services(desc
->type
))
95 type
= EFI_CONVENTIONAL_MEMORY
;
97 memcpy(dest
, desc
, map
->desc_size
);
99 if (!skip_bs
|| !prev
)
101 else if (desc
->physical_start
!= addr
)
103 else if (type
!= EFI_CONVENTIONAL_MEMORY
)
105 else if (prev
->type
!= EFI_CONVENTIONAL_MEMORY
)
109 prev
->num_pages
+= desc
->num_pages
;
112 dest
= efi_get_next_mem_desc(map
, dest
);
114 addr
= desc
->physical_start
+ (desc
->num_pages
<<
119 dest
->type
= EFI_TABLE_END
;
124 static void efi_print_mem_table(struct efi_entry_memmap
*map
,
125 struct efi_mem_desc
*desc
, bool skip_bs
)
127 u64 attr_seen
[ATTR_SEEN_MAX
];
132 printf(" # %-14s %10s %10s %10s %s\n", "Type", "Physical",
133 "Virtual", "Size", "Attributes");
135 /* Keep track of all the different attributes we have seen */
138 for (upto
= 0; desc
->type
!= EFI_TABLE_END
;
139 upto
++, desc
= efi_get_next_mem_desc(map
, desc
)) {
143 if (skip_bs
&& is_boot_services(desc
->type
))
145 if (desc
->physical_start
!= addr
) {
146 printf(" %-14s %010llx %10s %010llx\n", "<gap>",
147 addr
, "", desc
->physical_start
- addr
);
149 size
= desc
->num_pages
<< EFI_PAGE_SHIFT
;
151 name
= desc
->type
< ARRAY_SIZE(type_name
) ?
152 type_name
[desc
->type
] : "<invalid>";
153 printf("%2d %x:%-12s %010llx %010llx %010llx ", upto
,
154 desc
->type
, name
, desc
->physical_start
,
155 desc
->virtual_start
, size
);
156 if (desc
->attribute
& EFI_MEMORY_RUNTIME
)
158 printf("%llx", desc
->attribute
& ~EFI_MEMORY_RUNTIME
);
161 for (i
= 0; i
< attr_seen_count
; i
++) {
162 if (attr_seen
[i
] == desc
->attribute
)
165 if (i
== attr_seen_count
&& i
< ATTR_SEEN_MAX
)
166 attr_seen
[attr_seen_count
++] = desc
->attribute
;
167 addr
= desc
->physical_start
+ size
;
170 printf("\nAttributes key:\n");
171 for (i
= 0; i
< attr_seen_count
; i
++) {
172 u64 attr
= attr_seen
[i
];
176 printf("%c%llx: ", (attr
& EFI_MEMORY_RUNTIME
) ? 'r' : ' ',
177 attr
& ~EFI_MEMORY_RUNTIME
);
178 for (j
= 0, first
= true; j
< ARRAY_SIZE(mem_attr
); j
++) {
179 if (attr
& mem_attr
[j
].val
) {
184 printf("%s", mem_attr
[j
].name
);
190 printf("*Some areas are merged (use 'all' to see)\n");
193 static int do_efi_mem(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
195 struct efi_mem_desc
*desc
;
196 struct efi_entry_memmap
*map
;
200 skip_bs
= !argc
|| *argv
[0] != 'a';
201 ret
= efi_info_get(EFIET_MEMORY_MAP
, (void **)&map
, &size
);
204 printf("No EFI table available\n");
206 case -EPROTONOSUPPORT
:
207 printf("Incorrect EFI table version\n");
210 printf("EFI table at %lx, memory map %p, size %x, version %x, descr. size %#x\n",
211 gd
->arch
.table
, map
, size
, map
->version
, map
->desc_size
);
212 if (map
->version
!= EFI_MEM_DESC_VERSION
) {
213 printf("Incorrect memory map version\n");
214 ret
= -EPROTONOSUPPORT
;
218 desc
= efi_build_mem_table(map
, size
, skip_bs
);
224 efi_print_mem_table(map
, desc
, skip_bs
);
228 printf("Error: %d\n", ret
);
230 return ret
? CMD_RET_FAILURE
: 0;
233 static cmd_tbl_t efi_commands
[] = {
234 U_BOOT_CMD_MKENT(mem
, 1, 1, do_efi_mem
, "", ""),
237 static int do_efi(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
243 return CMD_RET_USAGE
;
244 efi_cmd
= find_cmd_tbl(argv
[1], efi_commands
, ARRAY_SIZE(efi_commands
));
247 if (!efi_cmd
|| argc
> efi_cmd
->maxargs
)
248 return CMD_RET_USAGE
;
250 ret
= efi_cmd
->cmd(efi_cmd
, flag
, argc
, argv
);
252 return cmd_process_error(efi_cmd
, ret
);
258 "mem [all] Dump memory information [include boot services]"