3737#include <grub/i18n.h>
3838#include <grub/net.h>
3939#include <grub/slaunch.h>
40+ #include <grub/time.h>
4041#if defined (__i386__ ) || defined (__x86_64__ )
4142#include <grub/macho.h>
4243#include <grub/i386/macho.h>
@@ -250,6 +251,57 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
250251 return file_path ;
251252}
252253
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+
253305static grub_err_t
254306grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused )),
255307 int argc , char * argv [])
@@ -265,6 +317,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
265317 grub_efi_handle_t dev_handle = 0 ;
266318 grub_efi_char16_t * cmdline = NULL ;
267319 grub_efi_handle_t image_handle = NULL ;
320+ grub_uint64_t before_time , after_time ;
321+ grub_err_t err ;
268322
269323 if (argc == 0 )
270324 return grub_error (GRUB_ERR_BAD_ARGUMENT , N_ ("filename expected" ));
@@ -291,7 +345,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
291345 grub_net_network_level_address_t addr ;
292346 struct grub_net_network_level_interface * inf ;
293347 grub_net_network_level_address_t gateway ;
294- grub_err_t err ;
295348
296349 err = grub_net_resolve_address (dev -> net -> server , & addr );
297350 if (err )
@@ -344,6 +397,20 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
344397 goto fail ;
345398 }
346399
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+
347414#if defined (__i386__ ) || defined (__x86_64__ )
348415 if (size >= (grub_ssize_t ) sizeof (struct grub_macho_fat_header ))
349416 {
0 commit comments