Blame view

cmd/qfw.c 4.66 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
f60df20aa   Miao Yan   x86: qemu: add fw...
2
  /*
7b63b1832   Bin Meng   x86: Correct typo...
3
   * (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com>
f60df20aa   Miao Yan   x86: qemu: add fw...
4
5
6
7
8
   */
  
  #include <common.h>
  #include <command.h>
  #include <errno.h>
186865900   Miao Yan   cmd: qfw: rename ...
9
  #include <qfw.h>
f60df20aa   Miao Yan   x86: qemu: add fw...
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  
  /*
   * This function prepares kernel for zboot. It loads kernel data
   * to 'load_addr', initrd to 'initrd_addr' and kernel command
   * line using qemu fw_cfg interface.
   */
  static int qemu_fwcfg_setup_kernel(void *load_addr, void *initrd_addr)
  {
  	char *data_addr;
  	uint32_t setup_size, kernel_size, cmdline_size, initrd_size;
  
  	qemu_fwcfg_read_entry(FW_CFG_SETUP_SIZE, 4, &setup_size);
  	qemu_fwcfg_read_entry(FW_CFG_KERNEL_SIZE, 4, &kernel_size);
  
  	if (setup_size == 0 || kernel_size == 0) {
  		printf("warning: no kernel available
  ");
  		return -1;
  	}
  
  	data_addr = load_addr;
  	qemu_fwcfg_read_entry(FW_CFG_SETUP_DATA,
  			      le32_to_cpu(setup_size), data_addr);
  	data_addr += le32_to_cpu(setup_size);
  
  	qemu_fwcfg_read_entry(FW_CFG_KERNEL_DATA,
  			      le32_to_cpu(kernel_size), data_addr);
  	data_addr += le32_to_cpu(kernel_size);
  
  	data_addr = initrd_addr;
  	qemu_fwcfg_read_entry(FW_CFG_INITRD_SIZE, 4, &initrd_size);
  	if (initrd_size == 0) {
  		printf("warning: no initrd available
  ");
  	} else {
  		qemu_fwcfg_read_entry(FW_CFG_INITRD_DATA,
  				      le32_to_cpu(initrd_size), data_addr);
  		data_addr += le32_to_cpu(initrd_size);
  	}
  
  	qemu_fwcfg_read_entry(FW_CFG_CMDLINE_SIZE, 4, &cmdline_size);
  	if (cmdline_size) {
  		qemu_fwcfg_read_entry(FW_CFG_CMDLINE_DATA,
  				      le32_to_cpu(cmdline_size), data_addr);
  		/*
  		 * if kernel cmdline only contains '\0', (e.g. no -append
  		 * when invoking qemu), do not update bootargs
  		 */
  		if (*data_addr != '\0') {
382bee57f   Simon Glass   env: Rename seten...
59
  			if (env_set("bootargs", data_addr) < 0)
f60df20aa   Miao Yan   x86: qemu: add fw...
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  				printf("warning: unable to change bootargs
  ");
  		}
  	}
  
  	printf("loading kernel to address %p size %x", load_addr,
  	       le32_to_cpu(kernel_size));
  	if (initrd_size)
  		printf(" initrd %p size %x
  ",
  		       initrd_addr,
  		       le32_to_cpu(initrd_size));
  	else
  		printf("
  ");
  
  	return 0;
  }
25757220d   Miao Yan   x86: qemu: re-str...
78
79
80
  static int qemu_fwcfg_list_firmware(void)
  {
  	int ret;
099b2196e   Miao Yan   cmd: qfw: add API...
81
  	struct fw_cfg_file_iter iter;
25757220d   Miao Yan   x86: qemu: re-str...
82
83
84
85
86
87
  	struct fw_file *file;
  
  	/* make sure fw_list is loaded */
  	ret = qemu_fwcfg_read_firmware_list();
  	if (ret)
  		return ret;
099b2196e   Miao Yan   cmd: qfw: add API...
88
89
90
91
  
  	for (file = qemu_fwcfg_file_iter_init(&iter);
  	     !qemu_fwcfg_file_iter_end(&iter);
  	     file = qemu_fwcfg_file_iter_next(&iter)) {
25757220d   Miao Yan   x86: qemu: re-str...
92
93
94
  		printf("%-56s
  ", file->cfg.name);
  	}
f60df20aa   Miao Yan   x86: qemu: add fw...
95
96
  	return 0;
  }
f60df20aa   Miao Yan   x86: qemu: add fw...
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  static int qemu_fwcfg_do_list(cmd_tbl_t *cmdtp, int flag,
  		int argc, char * const argv[])
  {
  	if (qemu_fwcfg_list_firmware() < 0)
  		return CMD_RET_FAILURE;
  
  	return 0;
  }
  
  static int qemu_fwcfg_do_cpus(cmd_tbl_t *cmdtp, int flag,
  		int argc, char * const argv[])
  {
  	int ret = qemu_fwcfg_online_cpus();
  	if (ret < 0) {
  		printf("QEMU fw_cfg interface not found
  ");
  		return CMD_RET_FAILURE;
  	}
  
  	printf("%d cpu(s) online
  ", qemu_fwcfg_online_cpus());
  
  	return 0;
  }
  
  static int qemu_fwcfg_do_load(cmd_tbl_t *cmdtp, int flag,
  		int argc, char * const argv[])
  {
  	char *env;
  	void *load_addr;
  	void *initrd_addr;
00caae6d4   Simon Glass   env: Rename geten...
128
  	env = env_get("loadaddr");
f60df20aa   Miao Yan   x86: qemu: add fw...
129
130
  	load_addr = env ?
  		(void *)simple_strtoul(env, NULL, 16) :
86e30e67a   Miao Yan   cmd: qfw: do not ...
131
  #ifdef CONFIG_LOADADDR
f60df20aa   Miao Yan   x86: qemu: add fw...
132
  		(void *)CONFIG_LOADADDR;
86e30e67a   Miao Yan   cmd: qfw: do not ...
133
134
135
  #else
  		NULL;
  #endif
f60df20aa   Miao Yan   x86: qemu: add fw...
136

00caae6d4   Simon Glass   env: Rename geten...
137
  	env = env_get("ramdiskaddr");
f60df20aa   Miao Yan   x86: qemu: add fw...
138
139
  	initrd_addr = env ?
  		(void *)simple_strtoul(env, NULL, 16) :
86e30e67a   Miao Yan   cmd: qfw: do not ...
140
  #ifdef CONFIG_RAMDISK_ADDR
f60df20aa   Miao Yan   x86: qemu: add fw...
141
  		(void *)CONFIG_RAMDISK_ADDR;
86e30e67a   Miao Yan   cmd: qfw: do not ...
142
143
144
  #else
  		NULL;
  #endif
f60df20aa   Miao Yan   x86: qemu: add fw...
145
146
147
148
149
150
151
  
  	if (argc == 2) {
  		load_addr = (void *)simple_strtoul(argv[0], NULL, 16);
  		initrd_addr = (void *)simple_strtoul(argv[1], NULL, 16);
  	} else if (argc == 1) {
  		load_addr = (void *)simple_strtoul(argv[0], NULL, 16);
  	}
86e30e67a   Miao Yan   cmd: qfw: do not ...
152
153
154
155
156
  	if (!load_addr || !initrd_addr) {
  		printf("missing load or initrd address
  ");
  		return CMD_RET_FAILURE;
  	}
f60df20aa   Miao Yan   x86: qemu: add fw...
157
158
159
160
161
162
163
164
165
166
167
168
169
  	return qemu_fwcfg_setup_kernel(load_addr, initrd_addr);
  }
  
  static cmd_tbl_t fwcfg_commands[] = {
  	U_BOOT_CMD_MKENT(list, 0, 1, qemu_fwcfg_do_list, "", ""),
  	U_BOOT_CMD_MKENT(cpus, 0, 1, qemu_fwcfg_do_cpus, "", ""),
  	U_BOOT_CMD_MKENT(load, 2, 1, qemu_fwcfg_do_load, "", ""),
  };
  
  static int do_qemu_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
  	int ret;
  	cmd_tbl_t *fwcfg_cmd;
d3ad06239   Miao Yan   cmd: qfw: make fw...
170
  	if (!qemu_fwcfg_present()) {
f60df20aa   Miao Yan   x86: qemu: add fw...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
  		printf("QEMU fw_cfg interface not found
  ");
  		return CMD_RET_USAGE;
  	}
  
  	fwcfg_cmd = find_cmd_tbl(argv[1], fwcfg_commands,
  				 ARRAY_SIZE(fwcfg_commands));
  	argc -= 2;
  	argv += 2;
  	if (!fwcfg_cmd || argc > fwcfg_cmd->maxargs)
  		return CMD_RET_USAGE;
  
  	ret = fwcfg_cmd->cmd(fwcfg_cmd, flag, argc, argv);
  
  	return cmd_process_error(fwcfg_cmd, ret);
  }
  
  U_BOOT_CMD(
  	qfw,	4,	1,	do_qemu_fw,
  	"QEMU firmware interface",
  	"<command>
  "
  	"    - list                             : print firmware(s) currently loaded
  "
  	"    - cpus                             : print online cpu number
  "
  	"    - load <kernel addr> <initrd addr> : load kernel and initrd (if any), and setup for zboot
  "
  )