/* ****************************************************************** */ static ssize_t ppc_rtas_progress_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { unsigned long hex; if (count >= MAX_LINELENGTH) count = MAX_LINELENGTH -1; if (copy_from_user(progress_led, buf, count)) { /* save the string */ return -EFAULT; } progress_led[count] = 0; /* Lets see if the user passed hexdigits */ hex = simple_strtoul(progress_led, NULL, 10); rtas_progress ((char *)progress_led, hex); return count; /* clear the line */ /* rtas_progress(" ", 0xffff);*/ }
static void rtas_flash_firmware(int reboot_type) { unsigned long image_size; struct flash_block_list *f, *next, *flist; unsigned long rtas_block_list; int i, status, update_token; if (rtas_firmware_flash_list.next == NULL) return; /* nothing to do */ if (reboot_type != SYS_RESTART) { printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n"); printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n"); return; } update_token = rtas_token("ibm,update-flash-64-and-reboot"); if (update_token == RTAS_UNKNOWN_SERVICE) { printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot " "is not available -- not a service partition?\n"); printk(KERN_ALERT "FLASH: firmware will not be flashed\n"); return; } /* NOTE: the "first" block list is a global var with no data * blocks in the kernel data segment. We do this because * we want to ensure this block_list addr is under 4GB. */ rtas_firmware_flash_list.num_blocks = 0; flist = (struct flash_block_list *)&rtas_firmware_flash_list; rtas_block_list = virt_to_abs(flist); if (rtas_block_list >= 4UL*1024*1024*1024) { printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n"); return; } printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n"); /* Update the block_list in place. */ image_size = 0; for (f = flist; f; f = next) { /* Translate data addrs to absolute */ for (i = 0; i < f->num_blocks; i++) { f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data); image_size += f->blocks[i].length; } next = f->next; /* Don't translate NULL pointer for last entry */ if (f->next) f->next = (struct flash_block_list *)virt_to_abs(f->next); else f->next = NULL; /* make num_blocks into the version/length field */ f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16); } printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size); printk(KERN_ALERT "FLASH: performing flash and reboot\n"); rtas_progress("Flashing \n", 0x0); rtas_progress("Please Wait... ", 0x0); printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n"); status = rtas_call(update_token, 1, 1, NULL, rtas_block_list); switch (status) { /* should only get "bad" status */ case 0: printk(KERN_ALERT "FLASH: success\n"); break; case -1: printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n"); break; case -3: printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n"); break; case -4: printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n"); break; default: printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status); break; } }
/* * On-reboot flash update applicator. */ static void rtas_flash_firmware(int reboot_type) { unsigned long image_size; struct flash_block_list *f, *next, *flist; unsigned long rtas_block_list; int i, status, update_token; if (rtas_firmware_flash_list == NULL) return; /* nothing to do */ if (reboot_type != SYS_RESTART) { printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n"); printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n"); return; } update_token = rtas_token("ibm,update-flash-64-and-reboot"); if (update_token == RTAS_UNKNOWN_SERVICE) { printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot " "is not available -- not a service partition?\n"); printk(KERN_ALERT "FLASH: firmware will not be flashed\n"); return; } /* * Just before starting the firmware flash, cancel the event scan work * to avoid any soft lockup issues. */ rtas_cancel_event_scan(); /* * NOTE: the "first" block must be under 4GB, so we create * an entry with no data blocks in the reserved buffer in * the kernel data segment. */ spin_lock(&rtas_data_buf_lock); flist = (struct flash_block_list *)&rtas_data_buf[0]; flist->num_blocks = 0; flist->next = rtas_firmware_flash_list; rtas_block_list = __pa(flist); if (rtas_block_list >= 4UL*1024*1024*1024) { printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n"); spin_unlock(&rtas_data_buf_lock); return; } printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n"); /* Update the block_list in place. */ rtas_firmware_flash_list = NULL; /* too hard to backout on error */ image_size = 0; for (f = flist; f; f = next) { /* Translate data addrs to absolute */ for (i = 0; i < f->num_blocks; i++) { f->blocks[i].data = (char *)cpu_to_be64(__pa(f->blocks[i].data)); image_size += f->blocks[i].length; f->blocks[i].length = cpu_to_be64(f->blocks[i].length); } next = f->next; /* Don't translate NULL pointer for last entry */ if (f->next) f->next = (struct flash_block_list *)cpu_to_be64(__pa(f->next)); else f->next = NULL; /* make num_blocks into the version/length field */ f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16); f->num_blocks = cpu_to_be64(f->num_blocks); } printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size); printk(KERN_ALERT "FLASH: performing flash and reboot\n"); rtas_progress("Flashing \n", 0x0); rtas_progress("Please Wait... ", 0x0); printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n"); status = rtas_call(update_token, 1, 1, NULL, rtas_block_list); switch (status) { /* should only get "bad" status */ case 0: printk(KERN_ALERT "FLASH: success\n"); break; case -1: printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n"); break; case -3: printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n"); break; case -4: printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n"); break; default: printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status); break; } spin_unlock(&rtas_data_buf_lock); }