aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbhay Salunke <Abhay_Salunke@dell.com>2005-09-06 18:17:14 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 19:57:27 -0400
commit6c54c28e69f2a374ad708fba37cbe1c5bb94e283 (patch)
treeaaa4f638443199becb53781b8b6eb669def702bd
parent6e3eaab02028c4087a92711b20abb9e72cc803a7 (diff)
[PATCH] dell_rbu: new Dell BIOS update driver
Remote BIOS Update driver for updating BIOS images on Dell servers and desktops. See dell_rbu.txt for details. Signed-off-by: Abhay Salunke <Abhay_Salunke@dell.com> Cc: Greg KH <greg@kroah.com> Signed-off-by: Jens Axboe <axboe@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--Documentation/dell_rbu.txt74
-rw-r--r--drivers/firmware/Kconfig9
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/dell_rbu.c634
4 files changed, 718 insertions, 0 deletions
diff --git a/Documentation/dell_rbu.txt b/Documentation/dell_rbu.txt
new file mode 100644
index 000000000000..bcfa5c35036b
--- /dev/null
+++ b/Documentation/dell_rbu.txt
@@ -0,0 +1,74 @@
1Purpose:
2Demonstrate the usage of the new open sourced rbu (Remote BIOS Update) driver
3for updating BIOS images on Dell servers and desktops.
4
5Scope:
6This document discusses the functionality of the rbu driver only.
7It does not cover the support needed from aplications to enable the BIOS to
8update itself with the image downloaded in to the memory.
9
10Overview:
11This driver works with Dell OpenManage or Dell Update Packages for updating
12the BIOS on Dell servers (starting from servers sold since 1999), desktops
13and notebooks (starting from those sold in 2005).
14Please go to http://support.dell.com register and you can find info on
15OpenManage and Dell Update packages (DUP).
16
17Dell_RBU driver supports BIOS update using the monilothic image and packetized
18image methods. In case of moniolithic the driver allocates a contiguous chunk
19of physical pages having the BIOS image. In case of packetized the app
20using the driver breaks the image in to packets of fixed sizes and the driver
21would place each packet in contiguous physical memory. The driver also
22maintains a link list of packets for reading them back.
23If the dell_rbu driver is unloaded all the allocated memory is freed.
24
25The rbu driver needs to have an application which will inform the BIOS to
26enable the update in the next system reboot.
27
28The user should not unload the rbu driver after downloading the BIOS image
29or updating.
30
31The driver load creates the following directories under the /sys file system.
32/sys/class/firmware/dell_rbu/loading
33/sys/class/firmware/dell_rbu/data
34/sys/devices/platform/dell_rbu/image_type
35/sys/devices/platform/dell_rbu/data
36
37The driver supports two types of update mechanism; monolithic and packetized.
38These update mechanism depends upon the BIOS currently running on the system.
39Most of the Dell systems support a monolithic update where the BIOS image is
40copied to a single contiguous block of physical memory.
41In case of packet mechanism the single memory can be broken in smaller chuks
42of contiguous memory and the BIOS image is scattered in these packets.
43
44By default the driver uses monolithic memory for the update type. This can be
45changed to contiguous during the driver load time by specifying the load
46parameter image_type=packet. This can also be changed later as below
47echo packet > /sys/devices/platform/dell_rbu/image_type
48
49Do the steps below to download the BIOS image.
501) echo 1 > /sys/class/firmware/dell_rbu/loading
512) cp bios_image.hdr /sys/class/firmware/dell_rbu/data
523) echo 0 > /sys/class/firmware/dell_rbu/loading
53
54The /sys/class/firmware/dell_rbu/ entries will remain till the following is
55done.
56echo -1 > /sys/class/firmware/dell_rbu/loading
57
58Until this step is completed the drivr cannot be unloaded.
59
60Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to
61read back the image downloaded. This is useful in case of packet update
62mechanism where the above steps 1,2,3 will repeated for every packet.
63By reading the /sys/devices/platform/dell_rbu/data file all packet data
64downloaded can be verified in a single file.
65The packets are arranged in this file one after the other in a FIFO order.
66
67NOTE:
68This driver requires a patch for firmware_class.c which has the addition
69of request_firmware_nowait_nohotplug function to wortk
70Also after updating the BIOS image an user mdoe application neeeds to execute
71code which message the BIOS update request to the BIOS. So on the next reboot
72the BIOS knows about the new image downloaded and it updates it self.
73Also don't unload the rbu drive if the image has to be updated.
74
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 5b29c3b2a331..b9b6e4273f01 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -58,4 +58,13 @@ config EFI_PCDP
58 58
59 See <http://www.dig64.org/specifications/DIG64_HCDPv20_042804.pdf> 59 See <http://www.dig64.org/specifications/DIG64_HCDPv20_042804.pdf>
60 60
61config DELL_RBU
62 tristate "BIOS update support for DELL systems via sysfs"
63 select FW_LOADER
64 help
65 Say m if you want to have the option of updating the BIOS for your
66 DELL system. Note you need a Dell OpenManage or Dell Update package (DUP)
67 supporting application to comunicate with the BIOS regarding the new
68 image for the image update to take effect.
69 See <file:Documentation/dell_rbu.txt> for more details on the driver.
61endmenu 70endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 90fd0b26db8b..186138572980 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -4,3 +4,4 @@
4obj-$(CONFIG_EDD) += edd.o 4obj-$(CONFIG_EDD) += edd.o
5obj-$(CONFIG_EFI_VARS) += efivars.o 5obj-$(CONFIG_EFI_VARS) += efivars.o
6obj-$(CONFIG_EFI_PCDP) += pcdp.o 6obj-$(CONFIG_EFI_PCDP) += pcdp.o
7obj-$(CONFIG_DELL_RBU) += dell_rbu.o
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
new file mode 100644
index 000000000000..3b865f34a095
--- /dev/null
+++ b/drivers/firmware/dell_rbu.c
@@ -0,0 +1,634 @@
1/*
2 * dell_rbu.c
3 * Bios Update driver for Dell systems
4 * Author: Dell Inc
5 * Abhay Salunke <abhay_salunke@dell.com>
6 *
7 * Copyright (C) 2005 Dell Inc.
8 *
9 * Remote BIOS Update (rbu) driver is used for updating DELL BIOS by
10 * creating entries in the /sys file systems on Linux 2.6 and higher
11 * kernels. The driver supports two mechanism to update the BIOS namely
12 * contiguous and packetized. Both these methods still require having some
13 * application to set the CMOS bit indicating the BIOS to update itself
14 * after a reboot.
15 *
16 * Contiguous method:
17 * This driver writes the incoming data in a monolithic image by allocating
18 * contiguous physical pages large enough to accommodate the incoming BIOS
19 * image size.
20 *
21 * Packetized method:
22 * The driver writes the incoming packet image by allocating a new packet
23 * on every time the packet data is written. This driver requires an
24 * application to break the BIOS image in to fixed sized packet chunks.
25 *
26 * See Documentation/dell_rbu.txt for more info.
27 *
28 * This program is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License v2.0 as published by
30 * the Free Software Foundation
31 *
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 */
37#include <linux/version.h>
38#include <linux/config.h>
39#include <linux/init.h>
40#include <linux/module.h>
41#include <linux/string.h>
42#include <linux/errno.h>
43#include <linux/blkdev.h>
44#include <linux/device.h>
45#include <linux/spinlock.h>
46#include <linux/moduleparam.h>
47#include <linux/firmware.h>
48#include <linux/dma-mapping.h>
49
50MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
51MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
52MODULE_LICENSE("GPL");
53MODULE_VERSION("1.0");
54
55#define BIOS_SCAN_LIMIT 0xffffffff
56#define MAX_IMAGE_LENGTH 16
57static struct _rbu_data {
58 void *image_update_buffer;
59 unsigned long image_update_buffer_size;
60 unsigned long bios_image_size;
61 int image_update_ordernum;
62 int dma_alloc;
63 spinlock_t lock;
64 unsigned long packet_read_count;
65 unsigned long packet_write_count;
66 unsigned long num_packets;
67 unsigned long packetsize;
68} rbu_data;
69
70static char image_type[MAX_IMAGE_LENGTH] = "mono";
71module_param_string(image_type, image_type, sizeof(image_type), 0);
72MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet");
73
74struct packet_data {
75 struct list_head list;
76 size_t length;
77 void *data;
78 int ordernum;
79};
80
81static struct packet_data packet_data_head;
82
83static struct platform_device *rbu_device;
84static int context;
85static dma_addr_t dell_rbu_dmaaddr;
86
87static void init_packet_head(void)
88{
89 INIT_LIST_HEAD(&packet_data_head.list);
90 rbu_data.packet_write_count = 0;
91 rbu_data.packet_read_count = 0;
92 rbu_data.num_packets = 0;
93 rbu_data.packetsize = 0;
94}
95
96static int fill_last_packet(void *data, size_t length)
97{
98 struct list_head *ptemp_list;
99 struct packet_data *packet = NULL;
100 int packet_count = 0;
101
102 pr_debug("fill_last_packet: entry \n");
103
104 if (!rbu_data.num_packets) {
105 pr_debug("fill_last_packet: num_packets=0\n");
106 return -ENOMEM;
107 }
108
109 packet_count = rbu_data.num_packets;
110
111 ptemp_list = (&packet_data_head.list)->prev;
112
113 packet = list_entry(ptemp_list, struct packet_data, list);
114
115 if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) {
116 pr_debug("dell_rbu:%s: packet size data "
117 "overrun\n", __FUNCTION__);
118 return -EINVAL;
119 }
120
121 pr_debug("fill_last_packet : buffer = %p\n", packet->data);
122
123 memcpy((packet->data + rbu_data.packet_write_count), data, length);
124
125 if ((rbu_data.packet_write_count + length) == rbu_data.packetsize) {
126 /*
127 * this was the last data chunk in the packet
128 * so reinitialize the packet data counter to zero
129 */
130 rbu_data.packet_write_count = 0;
131 } else
132 rbu_data.packet_write_count += length;
133
134 pr_debug("fill_last_packet: exit \n");
135 return 0;
136}
137
138static int create_packet(size_t length)
139{
140 struct packet_data *newpacket;
141 int ordernum = 0;
142
143 pr_debug("create_packet: entry \n");
144
145 if (!rbu_data.packetsize) {
146 pr_debug("create_packet: packetsize not specified\n");
147 return -EINVAL;
148 }
149
150 newpacket = kmalloc(sizeof(struct packet_data), GFP_KERNEL);
151 if (!newpacket) {
152 printk(KERN_WARNING
153 "dell_rbu:%s: failed to allocate new "
154 "packet\n", __FUNCTION__);
155 return -ENOMEM;
156 }
157
158 ordernum = get_order(length);
159 /*
160 * there is no upper limit on memory
161 * address for packetized mechanism
162 */
163 newpacket->data = (unsigned char *)__get_free_pages(GFP_KERNEL,
164 ordernum);
165
166 pr_debug("create_packet: newpacket %p\n", newpacket->data);
167
168 if (!newpacket->data) {
169 printk(KERN_WARNING
170 "dell_rbu:%s: failed to allocate new "
171 "packet\n", __FUNCTION__);
172 kfree(newpacket);
173 return -ENOMEM;
174 }
175
176 newpacket->ordernum = ordernum;
177 ++rbu_data.num_packets;
178 /*
179 * initialize the newly created packet headers
180 */
181 INIT_LIST_HEAD(&newpacket->list);
182 list_add_tail(&newpacket->list, &packet_data_head.list);
183 /*
184 * packets have fixed size
185 */
186 newpacket->length = rbu_data.packetsize;
187
188 pr_debug("create_packet: exit \n");
189
190 return 0;
191}
192
193static int packetize_data(void *data, size_t length)
194{
195 int rc = 0;
196
197 if (!rbu_data.packet_write_count) {
198 if ((rc = create_packet(length)))
199 return rc;
200 }
201 if ((rc = fill_last_packet(data, length)))
202 return rc;
203
204 return rc;
205}
206
207static int
208do_packet_read(char *data, struct list_head *ptemp_list,
209 int length, int bytes_read, int *list_read_count)
210{
211 void *ptemp_buf;
212 struct packet_data *newpacket = NULL;
213 int bytes_copied = 0;
214 int j = 0;
215
216 newpacket = list_entry(ptemp_list, struct packet_data, list);
217 *list_read_count += newpacket->length;
218
219 if (*list_read_count > bytes_read) {
220 /* point to the start of unread data */
221 j = newpacket->length - (*list_read_count - bytes_read);
222 /* point to the offset in the packet buffer */
223 ptemp_buf = (u8 *) newpacket->data + j;
224 /*
225 * check if there is enough room in
226 * * the incoming buffer
227 */
228 if (length > (*list_read_count - bytes_read))
229 /*
230 * copy what ever is there in this
231 * packet and move on
232 */
233 bytes_copied = (*list_read_count - bytes_read);
234 else
235 /* copy the remaining */
236 bytes_copied = length;
237 memcpy(data, ptemp_buf, bytes_copied);
238 }
239 return bytes_copied;
240}
241
242static int packet_read_list(char *data, size_t * pread_length)
243{
244 struct list_head *ptemp_list;
245 int temp_count = 0;
246 int bytes_copied = 0;
247 int bytes_read = 0;
248 int remaining_bytes = 0;
249 char *pdest = data;
250
251 /* check if we have any packets */
252 if (0 == rbu_data.num_packets)
253 return -ENOMEM;
254
255 remaining_bytes = *pread_length;
256 bytes_read = rbu_data.packet_read_count;
257
258 ptemp_list = (&packet_data_head.list)->next;
259 while (!list_empty(ptemp_list)) {
260 bytes_copied = do_packet_read(pdest, ptemp_list,
261 remaining_bytes, bytes_read,
262 &temp_count);
263 remaining_bytes -= bytes_copied;
264 bytes_read += bytes_copied;
265 pdest += bytes_copied;
266 /*
267 * check if we reached end of buffer before reaching the
268 * last packet
269 */
270 if (remaining_bytes == 0)
271 break;
272
273 ptemp_list = ptemp_list->next;
274 }
275 /*finally set the bytes read */
276 *pread_length = bytes_read - rbu_data.packet_read_count;
277 rbu_data.packet_read_count = bytes_read;
278 return 0;
279}
280
281static void packet_empty_list(void)
282{
283 struct list_head *ptemp_list;
284 struct list_head *pnext_list;
285 struct packet_data *newpacket;
286
287 ptemp_list = (&packet_data_head.list)->next;
288 while (!list_empty(ptemp_list)) {
289 newpacket =
290 list_entry(ptemp_list, struct packet_data, list);
291 pnext_list = ptemp_list->next;
292 list_del(ptemp_list);
293 ptemp_list = pnext_list;
294 /*
295 * zero out the RBU packet memory before freeing
296 * to make sure there are no stale RBU packets left in memory
297 */
298 memset(newpacket->data, 0, rbu_data.packetsize);
299 free_pages((unsigned long)newpacket->data,
300 newpacket->ordernum);
301 kfree(newpacket);
302 }
303 rbu_data.packet_write_count = 0;
304 rbu_data.packet_read_count = 0;
305 rbu_data.num_packets = 0;
306 rbu_data.packetsize = 0;
307}
308
309/*
310 * img_update_free: Frees the buffer allocated for storing BIOS image
311 * Always called with lock held and returned with lock held
312 */
313static void img_update_free(void)
314{
315 if (!rbu_data.image_update_buffer)
316 return;
317 /*
318 * zero out this buffer before freeing it to get rid of any stale
319 * BIOS image copied in memory.
320 */
321 memset(rbu_data.image_update_buffer, 0,
322 rbu_data.image_update_buffer_size);
323 if (rbu_data.dma_alloc == 1)
324 dma_free_coherent(NULL, rbu_data.bios_image_size,
325 rbu_data.image_update_buffer,
326 dell_rbu_dmaaddr);
327 else
328 free_pages((unsigned long)rbu_data.image_update_buffer,
329 rbu_data.image_update_ordernum);
330
331 /*
332 * Re-initialize the rbu_data variables after a free
333 */
334 rbu_data.image_update_ordernum = -1;
335 rbu_data.image_update_buffer = NULL;
336 rbu_data.image_update_buffer_size = 0;
337 rbu_data.bios_image_size = 0;
338 rbu_data.dma_alloc = 0;
339}
340
341/*
342 * img_update_realloc: This function allocates the contiguous pages to
343 * accommodate the requested size of data. The memory address and size
344 * values are stored globally and on every call to this function the new
345 * size is checked to see if more data is required than the existing size.
346 * If true the previous memory is freed and new allocation is done to
347 * accommodate the new size. If the incoming size is less then than the
348 * already allocated size, then that memory is reused. This function is
349 * called with lock held and returns with lock held.
350 */
351static int img_update_realloc(unsigned long size)
352{
353 unsigned char *image_update_buffer = NULL;
354 unsigned long rc;
355 unsigned long img_buf_phys_addr;
356 int ordernum;
357 int dma_alloc = 0;
358
359 /*
360 * check if the buffer of sufficient size has been
361 * already allocated
362 */
363 if (rbu_data.image_update_buffer_size >= size) {
364 /*
365 * check for corruption
366 */
367 if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
368 printk(KERN_ERR "dell_rbu:%s: corruption "
369 "check failed\n", __FUNCTION__);
370 return -EINVAL;
371 }
372 /*
373 * we have a valid pre-allocated buffer with
374 * sufficient size
375 */
376 return 0;
377 }
378
379 /*
380 * free any previously allocated buffer
381 */
382 img_update_free();
383
384 spin_unlock(&rbu_data.lock);
385
386 ordernum = get_order(size);
387 image_update_buffer =
388 (unsigned char *)__get_free_pages(GFP_KERNEL, ordernum);
389
390 img_buf_phys_addr =
391 (unsigned long)virt_to_phys(image_update_buffer);
392
393 if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
394 free_pages((unsigned long)image_update_buffer, ordernum);
395 ordernum = -1;
396 image_update_buffer = dma_alloc_coherent(NULL, size,
397 &dell_rbu_dmaaddr,
398 GFP_KERNEL);
399 dma_alloc = 1;
400 }
401
402 spin_lock(&rbu_data.lock);
403
404 if (image_update_buffer != NULL) {
405 rbu_data.image_update_buffer = image_update_buffer;
406 rbu_data.image_update_buffer_size = size;
407 rbu_data.bios_image_size =
408 rbu_data.image_update_buffer_size;
409 rbu_data.image_update_ordernum = ordernum;
410 rbu_data.dma_alloc = dma_alloc;
411 rc = 0;
412 } else {
413 pr_debug("Not enough memory for image update:"
414 "size = %ld\n", size);
415 rc = -ENOMEM;
416 }
417
418 return rc;
419}
420
421static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
422{
423 int retval;
424 size_t bytes_left;
425 size_t data_length;
426 char *ptempBuf = buffer;
427 unsigned long imagesize;
428
429 /* check to see if we have something to return */
430 if (rbu_data.num_packets == 0) {
431 pr_debug("read_packet_data: no packets written\n");
432 retval = -ENOMEM;
433 goto read_rbu_data_exit;
434 }
435
436 imagesize = rbu_data.num_packets * rbu_data.packetsize;
437
438 if (pos > imagesize) {
439 retval = 0;
440 printk(KERN_WARNING "dell_rbu:read_packet_data: "
441 "data underrun\n");
442 goto read_rbu_data_exit;
443 }
444
445 bytes_left = imagesize - pos;
446 data_length = min(bytes_left, count);
447
448 if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)
449 goto read_rbu_data_exit;
450
451 if ((pos + count) > imagesize) {
452 rbu_data.packet_read_count = 0;
453 /* this was the last copy */
454 retval = bytes_left;
455 } else
456 retval = count;
457
458 read_rbu_data_exit:
459 return retval;
460}
461
462static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
463{
464 unsigned char *ptemp = NULL;
465 size_t bytes_left = 0;
466 size_t data_length = 0;
467 ssize_t ret_count = 0;
468
469 /* check to see if we have something to return */
470 if ((rbu_data.image_update_buffer == NULL) ||
471 (rbu_data.bios_image_size == 0)) {
472 pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
473 "bios_image_size %lu\n",
474 rbu_data.image_update_buffer,
475 rbu_data.bios_image_size);
476 ret_count = -ENOMEM;
477 goto read_rbu_data_exit;
478 }
479
480 if (pos > rbu_data.bios_image_size) {
481 ret_count = 0;
482 goto read_rbu_data_exit;
483 }
484
485 bytes_left = rbu_data.bios_image_size - pos;
486 data_length = min(bytes_left, count);
487
488 ptemp = rbu_data.image_update_buffer;
489 memcpy(buffer, (ptemp + pos), data_length);
490
491 if ((pos + count) > rbu_data.bios_image_size)
492 /* this was the last copy */
493 ret_count = bytes_left;
494 else
495 ret_count = count;
496 read_rbu_data_exit:
497 return ret_count;
498}
499
500static ssize_t
501read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count)
502{
503 ssize_t ret_count = 0;
504
505 spin_lock(&rbu_data.lock);
506
507 if (!strcmp(image_type, "mono"))
508 ret_count = read_rbu_mono_data(buffer, pos, count);
509 else if (!strcmp(image_type, "packet"))
510 ret_count = read_packet_data(buffer, pos, count);
511 else
512 pr_debug("read_rbu_data: invalid image type specified\n");
513
514 spin_unlock(&rbu_data.lock);
515 return ret_count;
516}
517
518static ssize_t
519read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
520 size_t count)
521{
522 int size = 0;
523 if (!pos)
524 size = sprintf(buffer, "%s\n", image_type);
525 return size;
526}
527
528static ssize_t
529write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
530 size_t count)
531{
532 int rc = count;
533 spin_lock(&rbu_data.lock);
534
535 if (strlen(buffer) < MAX_IMAGE_LENGTH)
536 sscanf(buffer, "%s", image_type);
537 else
538 printk(KERN_WARNING "dell_rbu: image_type is invalid"
539 "max chars = %d, \n incoming str--%s-- \n",
540 MAX_IMAGE_LENGTH, buffer);
541
542 /* we must free all previous allocations */
543 packet_empty_list();
544 img_update_free();
545
546 spin_unlock(&rbu_data.lock);
547 return rc;
548
549}
550
551static struct bin_attribute rbu_data_attr = {
552 .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
553 .read = read_rbu_data,
554};
555
556static struct bin_attribute rbu_image_type_attr = {
557 .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
558 .read = read_rbu_image_type,
559 .write = write_rbu_image_type,
560};
561
562static void callbackfn_rbu(const struct firmware *fw, void *context)
563{
564 int rc = 0;
565
566 if (!fw || !fw->size)
567 return;
568
569 spin_lock(&rbu_data.lock);
570 if (!strcmp(image_type, "mono")) {
571 if (!img_update_realloc(fw->size))
572 memcpy(rbu_data.image_update_buffer,
573 fw->data, fw->size);
574 } else if (!strcmp(image_type, "packet")) {
575 if (!rbu_data.packetsize)
576 rbu_data.packetsize = fw->size;
577 else if (rbu_data.packetsize != fw->size) {
578 packet_empty_list();
579 rbu_data.packetsize = fw->size;
580 }
581 packetize_data(fw->data, fw->size);
582 } else
583 pr_debug("invalid image type specified.\n");
584 spin_unlock(&rbu_data.lock);
585
586 rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
587 "dell_rbu", &rbu_device->dev,
588 &context, callbackfn_rbu);
589 if (rc)
590 printk(KERN_ERR
591 "dell_rbu:%s request_firmware_nowait failed"
592 " %d\n", __FUNCTION__, rc);
593}
594
595static int __init dcdrbu_init(void)
596{
597 int rc = 0;
598 spin_lock_init(&rbu_data.lock);
599
600 init_packet_head();
601 rbu_device =
602 platform_device_register_simple("dell_rbu", -1, NULL, 0);
603 if (!rbu_device) {
604 printk(KERN_ERR
605 "dell_rbu:%s:platform_device_register_simple "
606 "failed\n", __FUNCTION__);
607 return -EIO;
608 }
609
610 sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
611 sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
612
613 rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
614 "dell_rbu", &rbu_device->dev,
615 &context, callbackfn_rbu);
616 if (rc)
617 printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait"
618 " failed %d\n", __FUNCTION__, rc);
619
620 return rc;
621
622}
623
624static __exit void dcdrbu_exit(void)
625{
626 spin_lock(&rbu_data.lock);
627 packet_empty_list();
628 img_update_free();
629 spin_unlock(&rbu_data.lock);
630 platform_device_unregister(rbu_device);
631}
632
633module_exit(dcdrbu_exit);
634module_init(dcdrbu_init);