summaryrefslogtreecommitdiffstats
path: root/package/kexec-tools/patches/0005-ps3-kexec-load-legacy-kernel-hack.patch
blob: 6b7b37681dd402febe58c07a480465beb56a366a (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
Hack to load PS3 legacy kernels (2.6.16 and fc7 installer) with the 2.6.23
mainline linux kernel.

---
 kexec/arch/ppc64/fs2dt.c           |   47 +++++++++++++++++++++++++++++++++++++
 kexec/arch/ppc64/kexec-elf-ppc64.c |   44 ++++++++++++++++++++++++++++++++++
 kexec/arch/ppc64/kexec-ppc64.c     |    5 +++
 kexec/arch/ppc64/kexec-ppc64.h     |    2 +
 4 files changed, 98 insertions(+)

--- a/kexec/arch/ppc64/fs2dt.c
+++ b/kexec/arch/ppc64/fs2dt.c
@@ -262,6 +262,33 @@ static void putprops(char *fn, struct di
 			die("unrecoverable error: could not read \"%s\": %s\n",
 			    pathname, strerror(errno));
 
+		/* ps3 legacy - Add 'PS3PF' to compatible */
+
+		if (ps3_legacy && !strcmp(dp->d_name, "compatible")) {
+			static const char s[] = "PS3PF";
+			char *const tmp = (char *)dt + len;
+
+			memcpy(tmp, s, sizeof(s));
+			len += sizeof(s);
+			*dt_len = len;
+
+			fprintf(stdout, "ps3 legacy: Changed dt entry "
+				"/compatible: <%s> -> <%s %s>\n",
+				(char *)dt, (char *)dt, tmp);
+		}
+
+		/* ps3 legacy - force memory.reg to 224 MiB */
+
+		if (ps3_legacy && !strcmp(dp->d_name, "reg") && len == 16) {
+			uint64_t tmp = *((uint64_t *)dt + 1);
+
+			*((uint64_t *)dt + 1) = 0xe000000ULL;
+			fprintf(stdout, "ps3 legacy: Changed dt entry "
+				"/memory/reg: <%llx> -> <%llx>\n",
+				(unsigned long long)tmp,
+				*((unsigned long long *)dt + 1));
+		}
+
 		checkprop(fn, dt, len);
 
 		dt += (len + 3)/4;
@@ -360,6 +387,26 @@ static void putnode(void)
 		reserve(initrd_base, initrd_size);
 	}
 
+	/* ps3 legacy - add entry linux,platform <801> */
+
+	if (ps3_legacy && !strcmp(basename,"/chosen/")) {
+		int len = 4;
+		static const uint32_t data = 0x801UL;
+
+		*dt++ = 3;
+		*dt++ = len;
+		*dt++ = propnum("linux,platform");
+
+		if ((len >= 8) && ((unsigned long)dt & 0x4))
+			dt++;
+
+		memcpy(dt,&data,len);
+		dt += (len + 3)/4;
+
+		fprintf(stdout, "ps3 legacy: Added dt entry "
+			"/chosen/linux,platform = <801>\n");
+	}
+
 	/* Add cmdline to the second kernel.  Check to see if the new
 	 * cmdline has a root=.  If not, use the old root= cmdline.  */
 	if (!strcmp(basename,"/chosen/")) {
--- a/kexec/arch/ppc64/kexec-elf-ppc64.c
+++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
@@ -45,6 +45,7 @@
 uint64_t initrd_base, initrd_size;
 unsigned char reuse_initrd = 0;
 const char *ramdisk;
+int ps3_legacy = -1; /* default to probe */
 
 int create_flatten_tree(struct kexec_info *, unsigned char **, unsigned long *,
 			char *);
@@ -76,6 +77,33 @@ void arch_reuse_initrd(void)
 	reuse_initrd = 1;
 }
 
+/**
+ * ps3_legacy_probe - Probe kernel version.
+ */
+
+static int ps3_legacy_probe(const char *p, off_t len)
+{
+	static const char d1[] = "linux,platform";    /* legacy 2.6.16 */
+	static const char d2[] = "2.6.21-1.3194.fc7"; /* fedora 7 installer */
+	const char *const end = p + len - sizeof(d2);
+
+	while(p < end) {
+		if (p[0] == d1[0] && !memcmp(p, d1, sizeof(d1) - 1)) {
+			fprintf(stdout, "ps3 legacy: Legacy kernel found: "
+				"'%s'\n", d1);
+			break;
+		}
+		if (p[0] == d2[0] && !memcmp(p, d2, sizeof(d2) - 1)) {
+			fprintf(stdout, "ps3 legacy: Legacy kernel found: "
+				"'%s'\n", d2);
+			break;
+		}
+		p++;
+	}
+
+	return (p != end);
+}
+
 int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 			struct kexec_info *info)
 {
@@ -102,6 +130,8 @@ int elf_ppc64_load(int argc, char **argv
 #define OPT_RAMDISK     (OPT_ARCH_MAX+1)
 #define OPT_DEVICETREEBLOB     (OPT_ARCH_MAX+2)
 #define OPT_ARGS_IGNORE		(OPT_ARCH_MAX+3)
+#define OPT_PS3_LEGACY (OPT_ARCH_MAX+4)
+#define OPT_PS3_LEGACY_NO (OPT_ARCH_MAX+5)
 
 	static const struct option options[] = {
 		KEXEC_ARCH_OPTIONS
@@ -111,6 +141,8 @@ int elf_ppc64_load(int argc, char **argv
 		{ "initrd",             1, NULL, OPT_RAMDISK },
 		{ "devicetreeblob",     1, NULL, OPT_DEVICETREEBLOB },
 		{ "args-linux",		0, NULL, OPT_ARGS_IGNORE },
+		{ "ps3-legacy",         0, NULL, OPT_PS3_LEGACY },
+		{ "ps3-no-legacy",      0, NULL, OPT_PS3_LEGACY_NO },
 		{ 0,                    0, NULL, 0 },
 	};
 
@@ -146,9 +178,18 @@ int elf_ppc64_load(int argc, char **argv
 			break;
 		case OPT_ARGS_IGNORE:
 			break;
+		case OPT_PS3_LEGACY:
+			ps3_legacy = 1;
+			break;
+		case OPT_PS3_LEGACY_NO:
+			ps3_legacy = 0;
+			break;
 		}
 	}
 
+	if (ps3_legacy == -1)
+		ps3_legacy = ps3_legacy_probe(buf, len);
+
 	cmdline_len = 0;
 	if (cmdline)
 		cmdline_len = strlen(cmdline) + 1;
@@ -158,6 +199,9 @@ int elf_ppc64_load(int argc, char **argv
 	if (ramdisk && reuse_initrd)
 		die("Can't specify --ramdisk or --initrd with --reuseinitrd\n");
 
+	if (ps3_legacy && devicetreeblob)
+		die("Can't specify --devicetreeblob with --ps3-legacy\n");
+
 	setup_memory_ranges(info->kexec_flags);
 
 	/* Need to append some command line parameters internally in case of
--- a/kexec/arch/ppc64/kexec-ppc64.c
+++ b/kexec/arch/ppc64/kexec-ppc64.c
@@ -650,6 +650,11 @@ void arch_usage(void)
 	fprintf(stderr, "     --initrd=<filename> same as --ramdisk.\n");
 	fprintf(stderr, "     --devicetreeblob=<filename> Specify device tree blob file.\n");
 	fprintf(stderr, "     --elf64-core-headers Prepare core headers in ELF64 format\n");
+	fprintf(stderr, "     --ps3-legacy    Make fixups needed to boot PS3 legacy kernels.\n");
+	fprintf(stderr, "                     The default is to probe the kernel type.\n");
+	fprintf(stderr, "     --ps3-no-legacy Do not make fixups needed to boot PS3 legacy\n");
+	fprintf(stderr, "                     kernels. The default is to probe the kernel\n");
+	fprintf(stderr, "                     type.\n");
 }
 
 struct arch_options_t arch_options = {
--- a/kexec/arch/ppc64/kexec-ppc64.h
+++ b/kexec/arch/ppc64/kexec-ppc64.h
@@ -41,4 +41,6 @@ typedef struct mem_rgns {
 
 extern mem_rgns_t usablemem_rgns;
 
+extern int ps3_legacy;
+
 #endif /* KEXEC_PPC64_H */