mirror of
				https://gitlab.com/qemu-project/qboot.git
				synced 2024-02-13 08:33:40 +08:00 
			
		
		
		
	Place setup_data at location specified by host
QEMU places setup_data at a particular location, which cannot be relocated due to it containing self references in absolute address terms. For this reason, it supplies the intended location in FW_CFG_SETUP_ADDR. That is what is used in the option ROMs provided by QEMU, use this too in qboot. This also has the effect of removing the 8k limit on the copied size, since the header is copied to the right location from the beginning. Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> Message-Id: <20220916133603.693135-1-Jason@zx2c4.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		 Jason A. Donenfeld
					Jason A. Donenfeld
				
			
				
					committed by
					
						 Paolo Bonzini
						Paolo Bonzini
					
				
			
			
				
	
			
			
			 Paolo Bonzini
						Paolo Bonzini
					
				
			
						parent
						
							a5300c4949
						
					
				
				
					commit
					8ca302e86d
				
			
							
								
								
									
										13
									
								
								fw_cfg.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								fw_cfg.c
									
									
									
									
									
								
							| @ -269,6 +269,7 @@ void boot_from_fwcfg(void) | ||||
| { | ||||
| 	struct linuxboot_args args; | ||||
| 	uint32_t kernel_size; | ||||
| 	enum { HEADER_PEEK_SIZE = 8192 }; | ||||
|  | ||||
| 	fw_cfg_select(FW_CFG_CMDLINE_SIZE); | ||||
| 	args.cmdline_size = fw_cfg_readl_le(); | ||||
| @ -282,15 +283,17 @@ void boot_from_fwcfg(void) | ||||
| 	kernel_size = fw_cfg_readl_le(); | ||||
| 	fw_cfg_select(FW_CFG_SETUP_SIZE); | ||||
| 	args.vmlinuz_size = kernel_size + fw_cfg_readl_le(); | ||||
| 	fw_cfg_select(FW_CFG_SETUP_ADDR); | ||||
| 	args.setup_addr = (void *)fw_cfg_readl_le(); | ||||
|  | ||||
| 	if (!args.vmlinuz_size) | ||||
| 		return; | ||||
|  | ||||
| 	fw_cfg_select(FW_CFG_SETUP_DATA); | ||||
| 	fw_cfg_read(args.header, sizeof(args.header)); | ||||
| 	fw_cfg_read(args.setup_addr, HEADER_PEEK_SIZE); | ||||
|  | ||||
| 	if (!parse_bzimage(&args)) { | ||||
| 		uint8_t *header = args.header; | ||||
| 		uint8_t *header = args.setup_addr; | ||||
|  | ||||
| 		if (ldl_p(header) == 0x464c457f)  /* ELF magic */ | ||||
| 			boot_pvh_from_fw_cfg(); | ||||
| @ -298,9 +301,9 @@ void boot_from_fwcfg(void) | ||||
| 	} | ||||
|  | ||||
| 	/* SETUP_DATA already selected */ | ||||
| 	if (args.setup_size > sizeof(args.header)) | ||||
| 		fw_cfg_read(args.setup_addr + sizeof(args.header), | ||||
| 			    args.setup_size - sizeof(args.header)); | ||||
| 	if (args.setup_size > HEADER_PEEK_SIZE) | ||||
| 		fw_cfg_read(args.setup_addr + HEADER_PEEK_SIZE, | ||||
| 			    args.setup_size - HEADER_PEEK_SIZE); | ||||
|  | ||||
| 	fw_cfg_select(FW_CFG_KERNEL_DATA); | ||||
| 	fw_cfg_read_entry(FW_CFG_KERNEL_DATA, args.kernel_addr, kernel_size); | ||||
|  | ||||
| @ -10,7 +10,6 @@ struct linuxboot_args { | ||||
|  | ||||
| 	/* Input */ | ||||
| 	uint32_t cmdline_size, vmlinuz_size, initrd_size; | ||||
| 	uint8_t header[8192]; | ||||
| }; | ||||
|  | ||||
| bool parse_bzimage(struct linuxboot_args *args); | ||||
|  | ||||
| @ -11,7 +11,7 @@ struct hvm_start_info start_info = {0}; | ||||
|  | ||||
| bool parse_bzimage(struct linuxboot_args *args) | ||||
| { | ||||
| 	uint8_t *header = args->header; | ||||
| 	uint8_t *header = args->setup_addr; | ||||
|  | ||||
| 	uint32_t real_addr, cmdline_addr, prot_addr, initrd_addr; | ||||
| 	uint32_t setup_size; | ||||
| @ -84,7 +84,6 @@ bool parse_bzimage(struct linuxboot_args *args) | ||||
| 	args->setup_size = (setup_size+1)*512; | ||||
| 	args->kernel_size = args->vmlinuz_size - setup_size; | ||||
| 	args->initrd_addr = (void *)initrd_addr; | ||||
| 	args->setup_addr = (void *)real_addr; | ||||
| 	args->kernel_addr = (void *)prot_addr; | ||||
| 	args->cmdline_addr = (void *)cmdline_addr; | ||||
| 	return true; | ||||
| @ -92,7 +91,6 @@ bool parse_bzimage(struct linuxboot_args *args) | ||||
|  | ||||
| void boot_bzimage(struct linuxboot_args *args) | ||||
| { | ||||
| 	memcpy(args->setup_addr, args->header, sizeof(args->header)); | ||||
| #ifdef BENCHMARK_HACK | ||||
| 	/* Exit just before getting to vmlinuz, so that it is easy | ||||
| 	 * to time/profile the firmware. | ||||
|  | ||||
		Reference in New Issue
	
	Block a user