efi_loader: unload applications upon Exit()
Implement unloading of images in the Exit() boot services: * unload images that are not yet started, * unload started applications, * unload drivers returning an error. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
		
							parent
							
								
									df116e81ea
								
							
						
					
					
						commit
						126a43f15b
					
				|  | @ -234,6 +234,7 @@ struct efi_loaded_image_obj { | ||||||
| 	struct jmp_buf_data exit_jmp; | 	struct jmp_buf_data exit_jmp; | ||||||
| 	EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, | 	EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, | ||||||
| 				     struct efi_system_table *st); | 				     struct efi_system_table *st); | ||||||
|  | 	u16 image_type; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ | ||||||
| #include <linux/libfdt_env.h> | #include <linux/libfdt_env.h> | ||||||
| #include <u-boot/crc.h> | #include <u-boot/crc.h> | ||||||
| #include <bootm.h> | #include <bootm.h> | ||||||
|  | #include <pe.h> | ||||||
| #include <watchdog.h> | #include <watchdog.h> | ||||||
| 
 | 
 | ||||||
| DECLARE_GLOBAL_DATA_PTR; | DECLARE_GLOBAL_DATA_PTR; | ||||||
|  | @ -2798,7 +2799,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, | ||||||
| 	 *	 image protocol. | 	 *	 image protocol. | ||||||
| 	 */ | 	 */ | ||||||
| 	efi_status_t ret; | 	efi_status_t ret; | ||||||
| 	void *info; | 	struct efi_loaded_image *loaded_image_protocol; | ||||||
| 	struct efi_loaded_image_obj *image_obj = | 	struct efi_loaded_image_obj *image_obj = | ||||||
| 		(struct efi_loaded_image_obj *)image_handle; | 		(struct efi_loaded_image_obj *)image_handle; | ||||||
| 
 | 
 | ||||||
|  | @ -2806,13 +2807,33 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, | ||||||
| 		  exit_data_size, exit_data); | 		  exit_data_size, exit_data); | ||||||
| 
 | 
 | ||||||
| 	/* Check parameters */ | 	/* Check parameters */ | ||||||
| 	if (image_handle != current_image) |  | ||||||
| 		goto out; |  | ||||||
| 	ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image, | 	ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image, | ||||||
| 					 &info, NULL, NULL, | 					 (void **)&loaded_image_protocol, | ||||||
|  | 					 NULL, NULL, | ||||||
| 					 EFI_OPEN_PROTOCOL_GET_PROTOCOL)); | 					 EFI_OPEN_PROTOCOL_GET_PROTOCOL)); | ||||||
| 	if (ret != EFI_SUCCESS) | 	if (ret != EFI_SUCCESS) { | ||||||
|  | 		ret = EFI_INVALID_PARAMETER; | ||||||
| 		goto out; | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Unloading of unstarted images */ | ||||||
|  | 	switch (image_obj->header.type) { | ||||||
|  | 	case EFI_OBJECT_TYPE_STARTED_IMAGE: | ||||||
|  | 		break; | ||||||
|  | 	case EFI_OBJECT_TYPE_LOADED_IMAGE: | ||||||
|  | 		efi_delete_image(image_obj, loaded_image_protocol); | ||||||
|  | 		ret = EFI_SUCCESS; | ||||||
|  | 		goto out; | ||||||
|  | 	default: | ||||||
|  | 		/* Handle does not refer to loaded image */ | ||||||
|  | 		ret = EFI_INVALID_PARAMETER; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	/* A started image can only be unloaded it is the last one started. */ | ||||||
|  | 	if (image_handle != current_image) { | ||||||
|  | 		ret = EFI_INVALID_PARAMETER; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Exit data is only foreseen in case of failure. */ | 	/* Exit data is only foreseen in case of failure. */ | ||||||
| 	if (exit_status != EFI_SUCCESS) { | 	if (exit_status != EFI_SUCCESS) { | ||||||
|  | @ -2822,6 +2843,9 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, | ||||||
| 		if (ret != EFI_SUCCESS) | 		if (ret != EFI_SUCCESS) | ||||||
| 			EFI_PRINT("%s: out of memory\n", __func__); | 			EFI_PRINT("%s: out of memory\n", __func__); | ||||||
| 	} | 	} | ||||||
|  | 	if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION || | ||||||
|  | 	    exit_status != EFI_SUCCESS) | ||||||
|  | 		efi_delete_image(image_obj, loaded_image_protocol); | ||||||
| 
 | 
 | ||||||
| 	/* Make sure entry/exit counts for EFI world cross-overs match */ | 	/* Make sure entry/exit counts for EFI world cross-overs match */ | ||||||
| 	EFI_EXIT(exit_status); | 	EFI_EXIT(exit_status); | ||||||
|  | @ -2837,7 +2861,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, | ||||||
| 
 | 
 | ||||||
| 	panic("EFI application exited"); | 	panic("EFI application exited"); | ||||||
| out: | out: | ||||||
| 	return EFI_EXIT(EFI_INVALID_PARAMETER); | 	return EFI_EXIT(ret); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
|  | @ -273,6 +273,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, | ||||||
| 		IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader; | 		IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader; | ||||||
| 		image_base = opt->ImageBase; | 		image_base = opt->ImageBase; | ||||||
| 		efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); | 		efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); | ||||||
|  | 		handle->image_type = opt->Subsystem; | ||||||
| 		efi_reloc = efi_alloc(virt_size, | 		efi_reloc = efi_alloc(virt_size, | ||||||
| 				      loaded_image_info->image_code_type); | 				      loaded_image_info->image_code_type); | ||||||
| 		if (!efi_reloc) { | 		if (!efi_reloc) { | ||||||
|  | @ -288,6 +289,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, | ||||||
| 		IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader; | 		IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader; | ||||||
| 		image_base = opt->ImageBase; | 		image_base = opt->ImageBase; | ||||||
| 		efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); | 		efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); | ||||||
|  | 		handle->image_type = opt->Subsystem; | ||||||
| 		efi_reloc = efi_alloc(virt_size, | 		efi_reloc = efi_alloc(virt_size, | ||||||
| 				      loaded_image_info->image_code_type); | 				      loaded_image_info->image_code_type); | ||||||
| 		if (!efi_reloc) { | 		if (!efi_reloc) { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue