opal-flash.c revision 3441f04b4b62758a798f9fbbf2047dfedf0329a5
1/*
2 * PowerNV OPAL Firmware Update Interface
3 *
4 * Copyright 2013 IBM Corp.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#define DEBUG
13
14#include <linux/kernel.h>
15#include <linux/reboot.h>
16#include <linux/init.h>
17#include <linux/kobject.h>
18#include <linux/sysfs.h>
19#include <linux/slab.h>
20#include <linux/mm.h>
21#include <linux/vmalloc.h>
22#include <linux/pagemap.h>
23
24#include <asm/opal.h>
25
26/* FLASH status codes */
27#define FLASH_NO_OP		-1099	/* No operation initiated by user */
28#define FLASH_NO_AUTH		-9002	/* Not a service authority partition */
29
30/* Validate image status values */
31#define VALIDATE_IMG_READY	-1001	/* Image ready for validation */
32#define VALIDATE_IMG_INCOMPLETE	-1002	/* User copied < VALIDATE_BUF_SIZE */
33
34/* Manage image status values */
35#define MANAGE_ACTIVE_ERR	-9001	/* Cannot overwrite active img */
36
37/* Flash image status values */
38#define FLASH_IMG_READY		0	/* Img ready for flash on reboot */
39#define FLASH_INVALID_IMG	-1003	/* Flash image shorter than expected */
40#define FLASH_IMG_NULL_DATA	-1004	/* Bad data in sg list entry */
41#define FLASH_IMG_BAD_LEN	-1005	/* Bad length in sg list entry */
42
43/* Manage operation tokens */
44#define FLASH_REJECT_TMP_SIDE	0	/* Reject temporary fw image */
45#define FLASH_COMMIT_TMP_SIDE	1	/* Commit temporary fw image */
46
47/* Update tokens */
48#define FLASH_UPDATE_CANCEL	0	/* Cancel update request */
49#define FLASH_UPDATE_INIT	1	/* Initiate update */
50
51/* Validate image update result tokens */
52#define VALIDATE_TMP_UPDATE	0     /* T side will be updated */
53#define VALIDATE_FLASH_AUTH	1     /* Partition does not have authority */
54#define VALIDATE_INVALID_IMG	2     /* Candidate image is not valid */
55#define VALIDATE_CUR_UNKNOWN	3     /* Current fixpack level is unknown */
56/*
57 * Current T side will be committed to P side before being replace with new
58 * image, and the new image is downlevel from current image
59 */
60#define VALIDATE_TMP_COMMIT_DL	4
61/*
62 * Current T side will be committed to P side before being replaced with new
63 * image
64 */
65#define VALIDATE_TMP_COMMIT	5
66/*
67 * T side will be updated with a downlevel image
68 */
69#define VALIDATE_TMP_UPDATE_DL	6
70/*
71 * The candidate image's release date is later than the system's firmware
72 * service entitlement date - service warranty period has expired
73 */
74#define VALIDATE_OUT_OF_WRNTY	7
75
76/* Validate buffer size */
77#define VALIDATE_BUF_SIZE	4096
78
79/* XXX: Assume candidate image size is <= 1GB */
80#define MAX_IMAGE_SIZE	0x40000000
81
82/* Image status */
83enum {
84	IMAGE_INVALID,
85	IMAGE_LOADING,
86	IMAGE_READY,
87};
88
89/* Candidate image data */
90struct image_data_t {
91	int		status;
92	void		*data;
93	uint32_t	size;
94};
95
96/* Candidate image header */
97struct image_header_t {
98	uint16_t	magic;
99	uint16_t	version;
100	uint32_t	size;
101};
102
103struct validate_flash_t {
104	int		status;		/* Return status */
105	void		*buf;		/* Candidate image buffer */
106	uint32_t	buf_size;	/* Image size */
107	uint32_t	result;		/* Update results token */
108};
109
110struct manage_flash_t {
111	int status;		/* Return status */
112};
113
114struct update_flash_t {
115	int status;		/* Return status */
116};
117
118static struct image_header_t	image_header;
119static struct image_data_t	image_data;
120static struct validate_flash_t	validate_flash_data;
121static struct manage_flash_t	manage_flash_data;
122static struct update_flash_t	update_flash_data;
123
124static DEFINE_MUTEX(image_data_mutex);
125
126/*
127 * Validate candidate image
128 */
129static inline void opal_flash_validate(void)
130{
131	long ret;
132	void *buf = validate_flash_data.buf;
133	__be32 size, result;
134
135	ret = opal_validate_flash(__pa(buf), &size, &result);
136
137	validate_flash_data.status = ret;
138	validate_flash_data.buf_size = be32_to_cpu(size);
139	validate_flash_data.result = be32_to_cpu(result);
140}
141
142/*
143 * Validate output format:
144 *     validate result token
145 *     current image version details
146 *     new image version details
147 */
148static ssize_t validate_show(struct kobject *kobj,
149			     struct kobj_attribute *attr, char *buf)
150{
151	struct validate_flash_t *args_buf = &validate_flash_data;
152	int len;
153
154	/* Candidate image is not validated */
155	if (args_buf->status < VALIDATE_TMP_UPDATE) {
156		len = sprintf(buf, "%d\n", args_buf->status);
157		goto out;
158	}
159
160	/* Result token */
161	len = sprintf(buf, "%d\n", args_buf->result);
162
163	/* Current and candidate image version details */
164	if ((args_buf->result != VALIDATE_TMP_UPDATE) &&
165	    (args_buf->result < VALIDATE_CUR_UNKNOWN))
166		goto out;
167
168	if (args_buf->buf_size > (VALIDATE_BUF_SIZE - len)) {
169		memcpy(buf + len, args_buf->buf, VALIDATE_BUF_SIZE - len);
170		len = VALIDATE_BUF_SIZE;
171	} else {
172		memcpy(buf + len, args_buf->buf, args_buf->buf_size);
173		len += args_buf->buf_size;
174	}
175out:
176	/* Set status to default */
177	args_buf->status = FLASH_NO_OP;
178	return len;
179}
180
181/*
182 * Validate candidate firmware image
183 *
184 * Note:
185 *   We are only interested in first 4K bytes of the
186 *   candidate image.
187 */
188static ssize_t validate_store(struct kobject *kobj,
189			      struct kobj_attribute *attr,
190			      const char *buf, size_t count)
191{
192	struct validate_flash_t *args_buf = &validate_flash_data;
193
194	if (buf[0] != '1')
195		return -EINVAL;
196
197	mutex_lock(&image_data_mutex);
198
199	if (image_data.status != IMAGE_READY ||
200	    image_data.size < VALIDATE_BUF_SIZE) {
201		args_buf->result = VALIDATE_INVALID_IMG;
202		args_buf->status = VALIDATE_IMG_INCOMPLETE;
203		goto out;
204	}
205
206	/* Copy first 4k bytes of candidate image */
207	memcpy(args_buf->buf, image_data.data, VALIDATE_BUF_SIZE);
208
209	args_buf->status = VALIDATE_IMG_READY;
210	args_buf->buf_size = VALIDATE_BUF_SIZE;
211
212	/* Validate candidate image */
213	opal_flash_validate();
214
215out:
216	mutex_unlock(&image_data_mutex);
217	return count;
218}
219
220/*
221 * Manage flash routine
222 */
223static inline void opal_flash_manage(uint8_t op)
224{
225	struct manage_flash_t *const args_buf = &manage_flash_data;
226
227	args_buf->status = opal_manage_flash(op);
228}
229
230/*
231 * Show manage flash status
232 */
233static ssize_t manage_show(struct kobject *kobj,
234			   struct kobj_attribute *attr, char *buf)
235{
236	struct manage_flash_t *const args_buf = &manage_flash_data;
237	int rc;
238
239	rc = sprintf(buf, "%d\n", args_buf->status);
240	/* Set status to default*/
241	args_buf->status = FLASH_NO_OP;
242	return rc;
243}
244
245/*
246 * Manage operations:
247 *   0 - Reject
248 *   1 - Commit
249 */
250static ssize_t manage_store(struct kobject *kobj,
251			    struct kobj_attribute *attr,
252			    const char *buf, size_t count)
253{
254	uint8_t op;
255	switch (buf[0]) {
256	case '0':
257		op = FLASH_REJECT_TMP_SIDE;
258		break;
259	case '1':
260		op = FLASH_COMMIT_TMP_SIDE;
261		break;
262	default:
263		return -EINVAL;
264	}
265
266	/* commit/reject temporary image */
267	opal_flash_manage(op);
268	return count;
269}
270
271/*
272 * OPAL update flash
273 */
274static int opal_flash_update(int op)
275{
276	struct opal_sg_list *list;
277	unsigned long addr;
278	int64_t rc = OPAL_PARAMETER;
279
280	if (op == FLASH_UPDATE_CANCEL) {
281		pr_alert("FLASH: Image update cancelled\n");
282		addr = '\0';
283		goto flash;
284	}
285
286	list = opal_vmalloc_to_sg_list(image_data.data, image_data.size);
287	if (!list)
288		goto invalid_img;
289
290	/* First entry address */
291	addr = __pa(list);
292
293	pr_alert("FLASH: Image is %u bytes\n", image_data.size);
294	pr_alert("FLASH: Image update requested\n");
295	pr_alert("FLASH: Image will be updated during system reboot\n");
296	pr_alert("FLASH: This will take several minutes. Do not power off!\n");
297
298flash:
299	rc = opal_update_flash(addr);
300
301invalid_img:
302	return rc;
303}
304
305/*
306 * Show candidate image status
307 */
308static ssize_t update_show(struct kobject *kobj,
309			   struct kobj_attribute *attr, char *buf)
310{
311	struct update_flash_t *const args_buf = &update_flash_data;
312	return sprintf(buf, "%d\n", args_buf->status);
313}
314
315/*
316 * Set update image flag
317 *  1 - Flash new image
318 *  0 - Cancel flash request
319 */
320static ssize_t update_store(struct kobject *kobj,
321			    struct kobj_attribute *attr,
322			    const char *buf, size_t count)
323{
324	struct update_flash_t *const args_buf = &update_flash_data;
325	int rc = count;
326
327	mutex_lock(&image_data_mutex);
328
329	switch (buf[0]) {
330	case '0':
331		if (args_buf->status == FLASH_IMG_READY)
332			opal_flash_update(FLASH_UPDATE_CANCEL);
333		args_buf->status = FLASH_NO_OP;
334		break;
335	case '1':
336		/* Image is loaded? */
337		if (image_data.status == IMAGE_READY)
338			args_buf->status =
339				opal_flash_update(FLASH_UPDATE_INIT);
340		else
341			args_buf->status = FLASH_INVALID_IMG;
342		break;
343	default:
344		rc = -EINVAL;
345	}
346
347	mutex_unlock(&image_data_mutex);
348	return rc;
349}
350
351/*
352 * Free image buffer
353 */
354static void free_image_buf(void)
355{
356	void *addr;
357	int size;
358
359	addr = image_data.data;
360	size = PAGE_ALIGN(image_data.size);
361	while (size > 0) {
362		ClearPageReserved(vmalloc_to_page(addr));
363		addr += PAGE_SIZE;
364		size -= PAGE_SIZE;
365	}
366	vfree(image_data.data);
367	image_data.data = NULL;
368	image_data.status = IMAGE_INVALID;
369}
370
371/*
372 * Allocate image buffer.
373 */
374static int alloc_image_buf(char *buffer, size_t count)
375{
376	void *addr;
377	int size;
378
379	if (count < sizeof(struct image_header_t)) {
380		pr_warn("FLASH: Invalid candidate image\n");
381		return -EINVAL;
382	}
383
384	memcpy(&image_header, (void *)buffer, sizeof(struct image_header_t));
385	image_data.size = be32_to_cpu(image_header.size);
386	pr_debug("FLASH: Candidate image size = %u\n", image_data.size);
387
388	if (image_data.size > MAX_IMAGE_SIZE) {
389		pr_warn("FLASH: Too large image\n");
390		return -EINVAL;
391	}
392	if (image_data.size < VALIDATE_BUF_SIZE) {
393		pr_warn("FLASH: Image is shorter than expected\n");
394		return -EINVAL;
395	}
396
397	image_data.data = vzalloc(PAGE_ALIGN(image_data.size));
398	if (!image_data.data) {
399		pr_err("%s : Failed to allocate memory\n", __func__);
400		return -ENOMEM;
401	}
402
403	/* Pin memory */
404	addr = image_data.data;
405	size = PAGE_ALIGN(image_data.size);
406	while (size > 0) {
407		SetPageReserved(vmalloc_to_page(addr));
408		addr += PAGE_SIZE;
409		size -= PAGE_SIZE;
410	}
411
412	image_data.status = IMAGE_LOADING;
413	return 0;
414}
415
416/*
417 * Copy candidate image
418 *
419 * Parse candidate image header to get total image size
420 * and pre-allocate required memory.
421 */
422static ssize_t image_data_write(struct file *filp, struct kobject *kobj,
423				struct bin_attribute *bin_attr,
424				char *buffer, loff_t pos, size_t count)
425{
426	int rc;
427
428	mutex_lock(&image_data_mutex);
429
430	/* New image ? */
431	if (pos == 0) {
432		/* Free memory, if already allocated */
433		if (image_data.data)
434			free_image_buf();
435
436		/* Cancel outstanding image update request */
437		if (update_flash_data.status == FLASH_IMG_READY)
438			opal_flash_update(FLASH_UPDATE_CANCEL);
439
440		/* Allocate memory */
441		rc = alloc_image_buf(buffer, count);
442		if (rc)
443			goto out;
444	}
445
446	if (image_data.status != IMAGE_LOADING) {
447		rc = -ENOMEM;
448		goto out;
449	}
450
451	if ((pos + count) > image_data.size) {
452		rc = -EINVAL;
453		goto out;
454	}
455
456	memcpy(image_data.data + pos, (void *)buffer, count);
457	rc = count;
458
459	/* Set image status */
460	if ((pos + count) == image_data.size) {
461		pr_debug("FLASH: Candidate image loaded....\n");
462		image_data.status = IMAGE_READY;
463	}
464
465out:
466	mutex_unlock(&image_data_mutex);
467	return rc;
468}
469
470/*
471 * sysfs interface :
472 *  OPAL uses below sysfs files for code update.
473 *  We create these files under /sys/firmware/opal.
474 *
475 *   image		: Interface to load candidate firmware image
476 *   validate_flash	: Validate firmware image
477 *   manage_flash	: Commit/Reject firmware image
478 *   update_flash	: Flash new firmware image
479 *
480 */
481static struct bin_attribute image_data_attr = {
482	.attr = {.name = "image", .mode = 0200},
483	.size = MAX_IMAGE_SIZE,	/* Limit image size */
484	.write = image_data_write,
485};
486
487static struct kobj_attribute validate_attribute =
488	__ATTR(validate_flash, 0600, validate_show, validate_store);
489
490static struct kobj_attribute manage_attribute =
491	__ATTR(manage_flash, 0600, manage_show, manage_store);
492
493static struct kobj_attribute update_attribute =
494	__ATTR(update_flash, 0600, update_show, update_store);
495
496static struct attribute *image_op_attrs[] = {
497	&validate_attribute.attr,
498	&manage_attribute.attr,
499	&update_attribute.attr,
500	NULL	/* need to NULL terminate the list of attributes */
501};
502
503static struct attribute_group image_op_attr_group = {
504	.attrs = image_op_attrs,
505};
506
507void __init opal_flash_init(void)
508{
509	int ret;
510
511	/* Allocate validate image buffer */
512	validate_flash_data.buf = kzalloc(VALIDATE_BUF_SIZE, GFP_KERNEL);
513	if (!validate_flash_data.buf) {
514		pr_err("%s : Failed to allocate memory\n", __func__);
515		return;
516	}
517
518	/* Make sure /sys/firmware/opal directory is created */
519	if (!opal_kobj) {
520		pr_warn("FLASH: opal kobject is not available\n");
521		goto nokobj;
522	}
523
524	/* Create the sysfs files */
525	ret = sysfs_create_group(opal_kobj, &image_op_attr_group);
526	if (ret) {
527		pr_warn("FLASH: Failed to create sysfs files\n");
528		goto nokobj;
529	}
530
531	ret = sysfs_create_bin_file(opal_kobj, &image_data_attr);
532	if (ret) {
533		pr_warn("FLASH: Failed to create sysfs files\n");
534		goto nosysfs_file;
535	}
536
537	/* Set default status */
538	validate_flash_data.status = FLASH_NO_OP;
539	manage_flash_data.status = FLASH_NO_OP;
540	update_flash_data.status = FLASH_NO_OP;
541	image_data.status = IMAGE_INVALID;
542	return;
543
544nosysfs_file:
545	sysfs_remove_group(opal_kobj, &image_op_attr_group);
546
547nokobj:
548	kfree(validate_flash_data.buf);
549	return;
550}
551