aboutsummaryrefslogtreecommitdiff
path: root/cmd/x86/zboot.c
blob: c9375fb417c149a0175fda15bad7218684f8551f (plain)
1
2
3
4
5
6
7
8
9
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
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
200
201
202
203
// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (c) 2011 The Chromium OS Authors.
 * (C) Copyright 2002
 * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
 */

#include <command.h>
#include <mapmem.h>
#include <vsprintf.h>
#include <asm/zimage.h>

static int do_zboot_start(struct cmd_tbl *cmdtp, int flag, int argc,
			  char *const argv[])
{
	const char *s;

	memset(&state, '\0', sizeof(state));
	if (argc >= 2) {
		/* argv[1] holds the address of the bzImage */
		s = argv[1];
	} else {
		s = env_get("fileaddr");
	}

	if (s)
		state.bzimage_addr = hextoul(s, NULL);

	if (argc >= 3) {
		/* argv[2] holds the size of the bzImage */
		state.bzimage_size = hextoul(argv[2], NULL);
	}

	if (argc >= 4)
		state.initrd_addr = hextoul(argv[3], NULL);
	if (argc >= 5)
		state.initrd_size = hextoul(argv[4], NULL);
	if (argc >= 6) {
		/*
		 * When the base_ptr is passed in, we assume that the image is
		 * already loaded at the address given by argv[1] and therefore
		 * the original bzImage is somewhere else, or not accessible.
		 * In any case, we don't need access to the bzImage since all
		 * the processing is assumed to be done.
		 *
		 * So set the base_ptr to the given address, use this arg as the
		 * load address and set bzimage_addr to 0 so we know that it
		 * cannot be proceesed (or processed again).
		 */
		state.base_ptr = (void *)hextoul(argv[5], NULL);
		state.load_address = state.bzimage_addr;
		state.bzimage_addr = 0;
	}
	if (argc >= 7)
		state.cmdline = env_get(argv[6]);

	return 0;
}

static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc,
			 char *const argv[])
{
	if (zboot_load())
		return CMD_RET_FAILURE;

	if (env_set_hex("zbootbase", map_to_sysmem(state.base_ptr)) ||
	    env_set_hex("zbootaddr", state.load_address))
		return CMD_RET_FAILURE;

	return 0;
}

static int do_zboot_setup(struct cmd_tbl *cmdtp, int flag, int argc,
			  char *const argv[])
{
	struct boot_params *base_ptr = state.base_ptr;

	if (!base_ptr) {
		printf("base is not set: use 'zboot load' first\n");
		return CMD_RET_FAILURE;
	}
	if (zboot_setup()) {
		puts("Setting up boot parameters failed ...\n");
		return CMD_RET_FAILURE;
	}

	return 0;
}

static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc,
			 char *const argv[])
{
	printf("Kernel loaded at %08lx, setup_base=%p\n",
	       state.load_address, state.base_ptr);

	return 0;
}

static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc,
		       char *const argv[])
{
	int ret;

	ret = zboot_go();
	printf("Kernel returned! (err=%d)\n", ret);

	return CMD_RET_FAILURE;
}

static int do_zboot_dump(struct cmd_tbl *cmdtp, int flag, int argc,
			 char *const argv[])
{
	struct boot_params *base_ptr = state.base_ptr;

	if (argc > 1)
		base_ptr = (void *)hextoul(argv[1], NULL);
	if (!base_ptr) {
		printf("No zboot setup_base\n");
		return CMD_RET_FAILURE;
	}
	zimage_dump(base_ptr, true);

	return 0;
}

/* Note: This defines the complete_zboot() function */
U_BOOT_SUBCMDS(zboot,
	U_BOOT_CMD_MKENT(start, 8, 1, do_zboot_start, "", ""),
	U_BOOT_CMD_MKENT(load, 1, 1, do_zboot_load, "", ""),
	U_BOOT_CMD_MKENT(setup, 1, 1, do_zboot_setup, "", ""),
	U_BOOT_CMD_MKENT(info, 1, 1, do_zboot_info, "", ""),
	U_BOOT_CMD_MKENT(go, 1, 1, do_zboot_go, "", ""),
	U_BOOT_CMD_MKENT(dump, 2, 1, do_zboot_dump, "", ""),
)

int do_zboot_states(struct cmd_tbl *cmdtp, int flag, int argc,
		    char *const argv[], int state_mask)
{
	int i;

	for (i = 0; i < ZBOOT_STATE_COUNT; i++) {
		struct cmd_tbl *cmd = &zboot_subcmds[i];
		int mask = 1 << i;
		int ret;

		if (mask & state_mask) {
			ret = cmd->cmd(cmd, flag, argc, argv);
			if (ret)
				return ret;
		}
	}

	return 0;
}

int do_zboot_parent(struct cmd_tbl *cmdtp, int flag, int argc,
		    char *const argv[], int *repeatable)
{
	/* determine if we have a sub command */
	if (argc > 1) {
		char *endp;

		hextoul(argv[1], &endp);
		/*
		 * endp pointing to nul means that argv[1] was just a valid
		 * number, so pass it along to the normal processing
		 */
		if (*endp)
			return do_zboot(cmdtp, flag, argc, argv, repeatable);
	}

	do_zboot_states(cmdtp, flag, argc, argv, ZBOOT_STATE_START |
			ZBOOT_STATE_LOAD | ZBOOT_STATE_SETUP |
			ZBOOT_STATE_INFO | ZBOOT_STATE_GO);

	return CMD_RET_FAILURE;
}

U_BOOT_CMDREP_COMPLETE(
	zboot, 8, do_zboot_parent, "Boot bzImage",
	"[addr] [size] [initrd addr] [initrd size] [setup] [cmdline]\n"
	"      addr -        The optional starting address of the bzimage.\n"
	"                    If not set it defaults to the environment\n"
	"                    variable \"fileaddr\".\n"
	"      size -        The optional size of the bzimage. Defaults to\n"
	"                    zero.\n"
	"      initrd addr - The address of the initrd image to use, if any.\n"
	"      initrd size - The size of the initrd image to use, if any.\n"
	"      setup -       The address of the kernel setup region, if this\n"
	"                    is not at addr\n"
	"      cmdline -     Environment variable containing the kernel\n"
	"                    command line, to override U-Boot's normal\n"
	"                    cmdline generation\n"
	"\n"
	"Sub-commands to do part of the zboot sequence:\n"
	"\tstart [addr [arg ...]] - specify arguments\n"
	"\tload   - load OS image\n"
	"\tsetup  - set up table\n"
	"\tinfo   - show summary info\n"
	"\tgo     - start OS\n"
	"\tdump [addr]    - dump info (optional address of boot params)",
	complete_zboot
);