mirror of
				https://gitlab.com/qemu-project/qboot.git
				synced 2024-02-13 08:33:40 +08:00 
			
		
		
		
	 94d3b1b5d1
			
		
	
	94d3b1b5d1
	
	
	
		
			
			alloc buffer in fseg memory and fill it with smbios anchor and tables which read from the fw_cfg, then check type0 table and rebuild it if it's not exist. mainly inspired by the seabios, and borrowed some code from it. Reviewed-by: Ben Luo <luoben@linux.alibaba.com> Signed-off-by: kaihuan.pkh <kaihuan.pkh@alibaba-inc.com>
		
			
				
	
	
		
			160 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			160 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "bios.h"
 | |
| #include "stdio.h"
 | |
| #include "fw_cfg.h"
 | |
| #include "string.h"
 | |
| #include "start_info.h"
 | |
| 
 | |
| extern struct hvm_start_info start_info;
 | |
| 
 | |
| struct loader_cmd {
 | |
| 	uint32_t cmd;
 | |
| 	union {
 | |
| #define CMD_QUIT 0
 | |
| #define CMD_ALLOC 1
 | |
| 		struct {
 | |
| 			char file[56];
 | |
| 			uint32_t align;
 | |
| 			uint8_t zone;
 | |
| 		} alloc;
 | |
| #define CMD_PTR 2
 | |
| 		struct {
 | |
| 			char dest[56];
 | |
| 			char src[56];
 | |
| 			uint32_t offset;
 | |
| 			uint8_t size;
 | |
| 		} ptr;
 | |
| #define CMD_CHECKSUM 3
 | |
| 		struct {
 | |
| 			char file[56];
 | |
| 			uint32_t offset;
 | |
| 			uint32_t start;
 | |
| 			uint32_t len;
 | |
| 		} checksum;
 | |
| 		uint8_t pad[124];
 | |
| 	};
 | |
| } __attribute__((__packed__));
 | |
| 
 | |
| enum {
 | |
| 	ALLOC_HIGH = 1,
 | |
| 	ALLOC_FSEG = 2
 | |
| };
 | |
| 
 | |
| static uint8_t *file_address[20];
 | |
| 
 | |
| static inline void *id_to_addr(int fw_cfg_id)
 | |
| {
 | |
| 	return file_address[fw_cfg_id];
 | |
| }
 | |
| 
 | |
| static inline void set_file_addr(int fw_cfg_id, void *p)
 | |
| {
 | |
| 	file_address[fw_cfg_id] = p;
 | |
| }
 | |
| 
 | |
| static void do_alloc(char *file, uint32_t align, uint8_t zone)
 | |
| {
 | |
| 	int id = fw_cfg_file_id(file);
 | |
| 	int n = fw_cfg_file_size(id);
 | |
| 	char *p;
 | |
| 
 | |
| 	if (id == -1)
 | |
| 		panic();
 | |
| 
 | |
| 	if (align < 16)
 | |
| 		align = 16;
 | |
| 
 | |
| 	if (zone == ALLOC_FSEG)
 | |
| 		p = malloc_fseg_align(n, align);
 | |
| 	else
 | |
| 		p = malloc_align(n, align);
 | |
| 
 | |
| 	set_file_addr(id, p);
 | |
| 	fw_cfg_read_file(id, p, n);
 | |
| 
 | |
| 	/* For PVH boot, save the PA where the RSDP is stored */
 | |
| 	if (zone == ALLOC_FSEG) {
 | |
| 		if (!memcmp(p, "RSD PTR ", 8)) {
 | |
| 			start_info.rsdp_paddr = (uintptr_t)id_to_addr(id);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void do_ptr(char *dest, char *src, uint32_t offset, uint8_t size)
 | |
| {
 | |
| 	char *p, *q;
 | |
| 	int id;
 | |
| 	union {
 | |
| 		long long ll;
 | |
| 		char b[8];
 | |
| 	} data;
 | |
| 
 | |
| 	id = fw_cfg_file_id(src);
 | |
| 	p = id_to_addr(id);
 | |
| 	if (!p)
 | |
| 		panic();
 | |
| 
 | |
| 	id = fw_cfg_file_id(dest);
 | |
| 	q = id_to_addr(id);
 | |
| 	if (!q)
 | |
| 		panic();
 | |
| 
 | |
| 	q += offset;
 | |
| 
 | |
| 	/* Assumes little endian */
 | |
| 	data.ll = 0;
 | |
| 	memcpy(&data.b, q, size);
 | |
| 	data.ll += (uintptr_t) p;
 | |
| 	memcpy(q, &data.b, size);
 | |
| }
 | |
| 
 | |
| static void do_checksum(char *file, uint32_t offset, uint32_t start, uint32_t len)
 | |
| {
 | |
| 	uint8_t *p;
 | |
| 	int id;
 | |
| 	int n;
 | |
| 
 | |
| 	id = fw_cfg_file_id(file);
 | |
| 	p = id_to_addr(id);
 | |
| 	if (!p)
 | |
| 		panic();
 | |
| 
 | |
| 	n = fw_cfg_file_size(id);
 | |
| 	if (offset >= n || n < start || len > n - start)
 | |
| 		panic();
 | |
| 
 | |
| 	p[offset] -= csum8(&p[start], len);
 | |
| }
 | |
| 
 | |
| void extract_acpi(void)
 | |
| {
 | |
| 	int id = fw_cfg_file_id("etc/table-loader");
 | |
| 	int n = fw_cfg_file_size(id);
 | |
| 	struct loader_cmd script[n / sizeof(struct loader_cmd)];
 | |
| 	int i;
 | |
| 
 | |
| 	if (!n)
 | |
| 		return;
 | |
| 
 | |
| 	fw_cfg_read_file(id, script, n);
 | |
| 
 | |
| 	for (i = 0; i < ARRAY_SIZE(script); i++) {
 | |
| 		struct loader_cmd *s = &script[i];
 | |
| 		switch(script[i].cmd) {
 | |
| 		case CMD_ALLOC:
 | |
| 			do_alloc(s->alloc.file, s->alloc.align, s->alloc.zone);
 | |
| 			break;
 | |
| 		case CMD_PTR:
 | |
| 			do_ptr(s->ptr.dest, s->ptr.src, s->ptr.offset, s->ptr.size);
 | |
| 			break;
 | |
| 		case CMD_CHECKSUM:
 | |
| 			do_checksum(s->checksum.file, s->checksum.offset,
 | |
| 				    s->checksum.start, s->checksum.len);
 | |
| 			break;
 | |
| 		case CMD_QUIT:
 | |
| 			return;
 | |
| 		default:
 | |
| 			panic();
 | |
| 		}
 | |
| 	}
 | |
| }
 |