summaryrefslogtreecommitdiffstats
path: root/0002-pxe-implement-fdtdir-extlinux.conf-tag.patch
blob: c81446f73bf1c753b98ccbaaab00dbb469fc08b8 (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
From 13b5a55b02e80735288d90f3d098b08fe8f10a10 Mon Sep 17 00:00:00 2001
From: Stephen Warren <swarren@nvidia.com>
Date: Tue, 28 Jan 2014 21:50:10 -0700
Subject: [PATCH 02/13] pxe: implement fdtdir extlinux.conf tag

pxe: implement fdtdir extlinux.conf tag

People who write (or scripts that auto-generate) extlinux.conf don't
want to know about HW-specific information such as FDT filenames. Create
a new extlinux.conf tag "fdtdir" that specifies only the directory where
FDT files are located, and defer all knowledge of the filename to U-Boot.
The algorithm implemented is:

==========
if $fdt_addr_r is set:
  if "fdt" tag was specified in extlinux.conf:
    load the FDT from the filename in the tag
  else if "fdtdir" tag was specified in extlinux.conf:
    if "fdtfile" is set in the environment:
      load the FDT from filename in "$fdtfile"
    else:
      load the FDT from some automatically generated filename

if no FDT file was loaded, and $fdtaddr is set:
  # This indicates an FDT packaged with firmware
  use the FDT at $fdtaddr
==========

A small part of an example /boot/extlinux.conf might be:

==========
LABEL primary
        LINUX zImage
        FDTDIR ./

LABEL failsafe
        LINUX bkp/zImage
        FDTDIR bkp/
==========

... with /boot/tegra20-seaboard.dtb or /boot/bkp/tegra20-seaboard.dtb
being loaded by the sysboot/pxe code.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 common/cmd_pxe.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 72 insertions(+), 6 deletions(-)

diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c
index 4f00b1a..2bd572d 100644
--- a/common/cmd_pxe.c
+++ b/common/cmd_pxe.c
@@ -445,6 +445,7 @@ struct pxe_label {
 	char *append;
 	char *initrd;
 	char *fdt;
+	char *fdtdir;
 	int ipappend;
 	int attempted;
 	int localboot;
@@ -517,6 +518,9 @@ static void label_destroy(struct pxe_label *label)
 	if (label->fdt)
 		free(label->fdt);
 
+	if (label->fdtdir)
+		free(label->fdtdir);
+
 	free(label);
 }
 
@@ -675,13 +679,67 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
 	bootm_argv[3] = getenv("fdt_addr_r");
 
 	/* if fdt label is defined then get fdt from server */
-	if (bootm_argv[3] && label->fdt) {
-		if (get_relfile_envaddr(cmdtp, label->fdt, "fdt_addr_r") < 0) {
-			printf("Skipping %s for failure retrieving fdt\n",
-					label->name);
-			return 1;
+	if (bootm_argv[3]) {
+		char *fdtfile = NULL;
+		char *fdtfilefree = NULL;
+
+		if (label->fdt) {
+			fdtfile = label->fdt;
+		} else if (label->fdtdir) {
+			fdtfile = getenv("fdtfile");
+			/*
+			 * For complex cases, it might be worth calling a
+			 * board- or SoC-provided function here to provide a
+			 * better default:
+			 *
+			 * if (!fdtfile)
+			 *     fdtfile = gen_fdtfile();
+			 *
+			 * If this is added, be sure to keep the default below,
+			 * or move it to the default weak implementation of
+			 * gen_fdtfile().
+			 */
+			if (!fdtfile) {
+				char *soc = getenv("soc");
+				char *board = getenv("board");
+				char *slash;
+
+				len = strlen(label->fdtdir);
+				if (!len)
+					slash = "./";
+				else if (label->fdtdir[len - 1] != '/')
+					slash = "/";
+				else
+					slash = "";
+
+				len = strlen(label->fdtdir) + strlen(slash) +
+					strlen(soc) + 1 + strlen(board) + 5;
+				fdtfilefree = malloc(len);
+				if (!fdtfilefree) {
+					printf("malloc fail (FDT filename)\n");
+					return 1;
+				}
+
+				snprintf(fdtfilefree, len, "%s%s%s-%s.dtb",
+					label->fdtdir, slash, soc, board);
+				fdtfile = fdtfilefree;
+			}
 		}
-	} else
+
+		if (fdtfile) {
+			int err = get_relfile_envaddr(cmdtp, fdtfile, "fdt_addr_r");
+			free(fdtfilefree);
+			if (err < 0) {
+				printf("Skipping %s for failure retrieving fdt\n",
+						label->name);
+				return 1;
+			}
+		} else {
+			bootm_argv[3] = NULL;
+		}
+	}
+
+	if (!bootm_argv[3])
 		bootm_argv[3] = getenv("fdt_addr");
 
 	if (bootm_argv[3])
@@ -716,6 +774,7 @@ enum token_type {
 	T_PROMPT,
 	T_INCLUDE,
 	T_FDT,
+	T_FDTDIR,
 	T_ONTIMEOUT,
 	T_IPAPPEND,
 	T_INVALID
@@ -747,6 +806,8 @@ static const struct token keywords[] = {
 	{"include", T_INCLUDE},
 	{"devicetree", T_FDT},
 	{"fdt", T_FDT},
+	{"devicetreedir", T_FDTDIR},
+	{"fdtdir", T_FDTDIR},
 	{"ontimeout", T_ONTIMEOUT,},
 	{"ipappend", T_IPAPPEND,},
 	{NULL, T_INVALID}
@@ -1135,6 +1196,11 @@ static int parse_label(char **c, struct pxe_menu *cfg)
 				err = parse_sliteral(c, &label->fdt);
 			break;
 
+		case T_FDTDIR:
+			if (!label->fdtdir)
+				err = parse_sliteral(c, &label->fdtdir);
+			break;
+
 		case T_LOCALBOOT:
 			label->localboot = 1;
 			err = parse_integer(c, &label->localboot_val);
-- 
1.8.5.3