3 * Procedures for firmware flash updates.
5 * Peter Bergner, IBM March 2001.
6 * Copyright (C) 2001 IBM.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
15 #include <linux/kernel.h>
16 #include <linux/types.h>
17 #include <linux/spinlock.h>
18 #include <linux/module.h>
19 #include <linux/init.h>
23 #include <asm/semaphore.h>
24 #include <asm/machdep.h>
26 #include <asm/param.h>
27 #include <asm/system.h>
28 #include <asm/abs_addr.h>
30 #include <asm/delay.h>
31 #include <asm/uaccess.h>
32 #include <asm/systemcfg.h>
34 struct flash_block_list_header rtas_firmware_flash_list
= {0, NULL
};
36 #define FLASH_BLOCK_LIST_VERSION (1UL)
38 static void rtas_flash_firmware(void)
40 unsigned long image_size
;
41 struct flash_block_list
*f
, *next
, *flist
;
42 unsigned long rtas_block_list
;
43 int i
, status
, update_token
;
45 update_token
= rtas_token("ibm,update-flash-64-and-reboot");
46 if (update_token
== RTAS_UNKNOWN_SERVICE
) {
47 printk(KERN_ALERT
"FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n");
48 printk(KERN_ALERT
"FLASH: firmware will not be flashed\n");
52 /* NOTE: the "first" block list is a global var with no data
53 * blocks in the kernel data segment. We do this because
54 * we want to ensure this block_list addr is under 4GB.
56 rtas_firmware_flash_list
.num_blocks
= 0;
57 flist
= (struct flash_block_list
*)&rtas_firmware_flash_list
;
58 rtas_block_list
= virt_to_abs(flist
);
59 if (rtas_block_list
>= 4UL*1024*1024*1024) {
60 printk(KERN_ALERT
"FLASH: kernel bug...flash list header addr above 4GB\n");
64 printk(KERN_ALERT
"FLASH: preparing saved firmware image for flash\n");
65 /* Update the block_list in place. */
67 for (f
= flist
; f
; f
= next
) {
68 /* Translate data addrs to absolute */
69 for (i
= 0; i
< f
->num_blocks
; i
++) {
70 f
->blocks
[i
].data
= (char *)virt_to_abs(f
->blocks
[i
].data
);
71 image_size
+= f
->blocks
[i
].length
;
74 /* Don't translate NULL pointer for last entry */
76 f
->next
= (struct flash_block_list
*)virt_to_abs(f
->next
);
79 /* make num_blocks into the version/length field */
80 f
->num_blocks
= (FLASH_BLOCK_LIST_VERSION
<< 56) | ((f
->num_blocks
+1)*16);
83 printk(KERN_ALERT
"FLASH: flash image is %ld bytes\n", image_size
);
84 printk(KERN_ALERT
"FLASH: performing flash and reboot\n");
85 rtas_progress("Flashing \n", 0x0);
86 rtas_progress("Please Wait... ", 0x0);
87 printk(KERN_ALERT
"FLASH: this will take several minutes. Do not power off!\n");
88 status
= rtas_call(update_token
, 1, 1, NULL
, rtas_block_list
);
89 switch (status
) { /* should only get "bad" status */
91 printk(KERN_ALERT
"FLASH: success\n");
94 printk(KERN_ALERT
"FLASH: hardware error. Firmware may not be not flashed\n");
97 printk(KERN_ALERT
"FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n");
100 printk(KERN_ALERT
"FLASH: flash failed when partially complete. System may not reboot\n");
103 printk(KERN_ALERT
"FLASH: unknown flash return code %d\n", status
);
108 void rtas_flash_bypass_warning(void)
110 printk(KERN_ALERT
"FLASH: firmware flash requires a reboot\n");
111 printk(KERN_ALERT
"FLASH: the firmware image will NOT be flashed\n");
115 void rtas_fw_restart(char *cmd
)
117 if (rtas_firmware_flash_list
.next
)
118 rtas_flash_firmware();
122 void rtas_fw_power_off(void)
124 if (rtas_firmware_flash_list
.next
)
125 rtas_flash_bypass_warning();
129 void rtas_fw_halt(void)
131 if (rtas_firmware_flash_list
.next
)
132 rtas_flash_bypass_warning();
136 EXPORT_SYMBOL(rtas_firmware_flash_list
);