rtas_fw.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. *
  3. * Procedures for firmware flash updates.
  4. *
  5. * Peter Bergner, IBM March 2001.
  6. * Copyright (C) 2001 IBM.
  7. *
  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.
  12. */
  13. #include <stdarg.h>
  14. #include <linux/kernel.h>
  15. #include <linux/types.h>
  16. #include <linux/spinlock.h>
  17. #include <linux/module.h>
  18. #include <linux/init.h>
  19. #include <asm/prom.h>
  20. #include <asm/rtas.h>
  21. #include <asm/semaphore.h>
  22. #include <asm/machdep.h>
  23. #include <asm/page.h>
  24. #include <asm/param.h>
  25. #include <asm/system.h>
  26. #include <asm/abs_addr.h>
  27. #include <asm/udbg.h>
  28. #include <asm/delay.h>
  29. #include <asm/uaccess.h>
  30. #include <asm/systemcfg.h>
  31. struct flash_block_list_header rtas_firmware_flash_list = {0, NULL};
  32. #define FLASH_BLOCK_LIST_VERSION (1UL)
  33. static void rtas_flash_firmware(void)
  34. {
  35. unsigned long image_size;
  36. struct flash_block_list *f, *next, *flist;
  37. unsigned long rtas_block_list;
  38. int i, status, update_token;
  39. update_token = rtas_token("ibm,update-flash-64-and-reboot");
  40. if (update_token == RTAS_UNKNOWN_SERVICE) {
  41. printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n");
  42. printk(KERN_ALERT "FLASH: firmware will not be flashed\n");
  43. return;
  44. }
  45. /* NOTE: the "first" block list is a global var with no data
  46. * blocks in the kernel data segment. We do this because
  47. * we want to ensure this block_list addr is under 4GB.
  48. */
  49. rtas_firmware_flash_list.num_blocks = 0;
  50. flist = (struct flash_block_list *)&rtas_firmware_flash_list;
  51. rtas_block_list = virt_to_abs(flist);
  52. if (rtas_block_list >= 4UL*1024*1024*1024) {
  53. printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
  54. return;
  55. }
  56. printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n");
  57. /* Update the block_list in place. */
  58. image_size = 0;
  59. for (f = flist; f; f = next) {
  60. /* Translate data addrs to absolute */
  61. for (i = 0; i < f->num_blocks; i++) {
  62. f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data);
  63. image_size += f->blocks[i].length;
  64. }
  65. next = f->next;
  66. /* Don't translate NULL pointer for last entry */
  67. if (f->next)
  68. f->next = (struct flash_block_list *)virt_to_abs(f->next);
  69. else
  70. f->next = NULL;
  71. /* make num_blocks into the version/length field */
  72. f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16);
  73. }
  74. printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);
  75. printk(KERN_ALERT "FLASH: performing flash and reboot\n");
  76. rtas_progress("Flashing \n", 0x0);
  77. rtas_progress("Please Wait... ", 0x0);
  78. printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n");
  79. status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);
  80. switch (status) { /* should only get "bad" status */
  81. case 0:
  82. printk(KERN_ALERT "FLASH: success\n");
  83. break;
  84. case -1:
  85. printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n");
  86. break;
  87. case -3:
  88. printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n");
  89. break;
  90. case -4:
  91. printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n");
  92. break;
  93. default:
  94. printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status);
  95. break;
  96. }
  97. }
  98. void rtas_flash_bypass_warning(void)
  99. {
  100. printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n");
  101. printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n");
  102. }
  103. void rtas_fw_restart(char *cmd)
  104. {
  105. if (rtas_firmware_flash_list.next)
  106. rtas_flash_firmware();
  107. rtas_restart(cmd);
  108. }
  109. void rtas_fw_power_off(void)
  110. {
  111. if (rtas_firmware_flash_list.next)
  112. rtas_flash_bypass_warning();
  113. rtas_power_off();
  114. }
  115. void rtas_fw_halt(void)
  116. {
  117. if (rtas_firmware_flash_list.next)
  118. rtas_flash_bypass_warning();
  119. rtas_halt();
  120. }
  121. EXPORT_SYMBOL(rtas_firmware_flash_list);