37
37
#include <grub/i18n.h>
38
38
#include <grub/net.h>
39
39
#include <grub/slaunch.h>
40
+ #include <grub/time.h>
40
41
#if defined (__i386__ ) || defined (__x86_64__ )
41
42
#include <grub/macho.h>
42
43
#include <grub/i386/macho.h>
@@ -250,6 +251,57 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
250
251
return file_path ;
251
252
}
252
253
254
+ /* Clear unused memory. This is meant to make measurements of DLME more
255
+ * deterministic in the face of firmware not bothering to zero area containing
256
+ * padding. */
257
+ static grub_err_t
258
+ clear_memory (void )
259
+ {
260
+ grub_efi_memory_descriptor_t * memory_map , * desc ;
261
+ grub_efi_uintn_t memory_map_size , desc_size ;
262
+ grub_efi_boot_services_t * b ;
263
+ grub_efi_uint64_t total_cleared = 0 ;
264
+ int ret ;
265
+
266
+ b = grub_efi_system_table -> boot_services ;
267
+
268
+ memory_map_size = grub_efi_find_mmap_size ();
269
+
270
+ memory_map = grub_malloc (memory_map_size );
271
+ if (!memory_map )
272
+ return GRUB_ERR_OUT_OF_MEMORY ;
273
+
274
+ ret = grub_efi_get_memory_map (& memory_map_size , memory_map , NULL ,
275
+ & desc_size , NULL );
276
+ if (ret < 1 )
277
+ return GRUB_ERR_BUG ;
278
+
279
+ for (desc = memory_map ;
280
+ (grub_addr_t ) desc < ((grub_addr_t ) memory_map + memory_map_size );
281
+ desc = (void * )((grub_uint8_t * )desc + desc_size ))
282
+ {
283
+ grub_efi_uint64_t size = desc -> num_pages << 12 ;
284
+
285
+ if (desc -> type != GRUB_EFI_CONVENTIONAL_MEMORY ||
286
+ desc -> physical_start >= (1ULL << 32 ))
287
+ continue ;
288
+
289
+ if (desc -> physical_start + size > (1ULL << 32 ))
290
+ size = (1ULL << 32 ) - desc -> physical_start ;
291
+
292
+ grub_dprintf ("chain" , "Clearing %lu bytes at 0x%lx...\n" , size ,
293
+ desc -> physical_start );
294
+ b -> set_mem ((void * )desc -> physical_start , size , 0x00 );
295
+ total_cleared += size ;
296
+ }
297
+
298
+ grub_free (memory_map );
299
+
300
+ grub_dprintf ("chain" , "Cleared %llu bytes in total.\n" ,
301
+ (unsigned long long )total_cleared );
302
+ return GRUB_ERR_NONE ;
303
+ }
304
+
253
305
static grub_err_t
254
306
grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused )),
255
307
int argc , char * argv [])
@@ -265,6 +317,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
265
317
grub_efi_handle_t dev_handle = 0 ;
266
318
grub_efi_char16_t * cmdline = NULL ;
267
319
grub_efi_handle_t image_handle = NULL ;
320
+ grub_uint64_t before_time , after_time ;
321
+ grub_err_t err ;
268
322
269
323
if (argc == 0 )
270
324
return grub_error (GRUB_ERR_BAD_ARGUMENT , N_ ("filename expected" ));
@@ -291,7 +345,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
291
345
grub_net_network_level_address_t addr ;
292
346
struct grub_net_network_level_interface * inf ;
293
347
grub_net_network_level_address_t gateway ;
294
- grub_err_t err ;
295
348
296
349
err = grub_net_resolve_address (dev -> net -> server , & addr );
297
350
if (err )
@@ -344,6 +397,20 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
344
397
goto fail ;
345
398
}
346
399
400
+ if (grub_slaunch_platform_type () != SLP_NONE )
401
+ {
402
+ before_time = grub_get_time_ms ();
403
+ err = clear_memory ();
404
+ after_time = grub_get_time_ms ();
405
+ grub_dprintf ("chain" , "Took %llu ms to clear the memory\n" ,
406
+ (unsigned long long )(after_time - before_time ));
407
+ if (err != GRUB_ERR_NONE )
408
+ {
409
+ grub_dprintf ("chain" , "Failed to clear unused memory < 4 GiB\n" );
410
+ goto fail ;
411
+ }
412
+ }
413
+
347
414
#if defined (__i386__ ) || defined (__x86_64__ )
348
415
if (size >= (grub_ssize_t ) sizeof (struct grub_macho_fat_header ))
349
416
{
0 commit comments