1/* 2 * 3 * Procedures for interfacing to the RTAS on CHRP machines. 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 14#include <stdarg.h> 15#include <linux/kernel.h> 16#include <linux/types.h> 17#include <linux/spinlock.h> 18#include <linux/fs.h> 19 20#include <asm/init.h> 21#include <asm/prom.h> 22#include <asm/rtas.h> 23#include <asm/semaphore.h> 24#include <asm/machdep.h> 25#include <asm/paca.h> 26#include <asm/page.h> 27#include <asm/system.h> 28#include <asm/abs_addr.h> 29#include <asm/udbg.h> 30 31struct proc_dir_entry *rtas_proc_dir; /* /proc/ppc64/rtas dir */ 32struct flash_block_list_header rtas_firmware_flash_list = {0, 0}; 33 34/* 35 * prom_init() is called very early on, before the kernel text 36 * and data have been mapped to KERNELBASE. At this point the code 37 * is running at whatever address it has been loaded at, so 38 * references to extern and static variables must be relocated 39 * explicitly. The procedure reloc_offset() returns the address 40 * we're currently running at minus the address we were linked at. 41 * (Note that strings count as static variables.) 42 * 43 * Because OF may have mapped I/O devices into the area starting at 44 * KERNELBASE, particularly on CHRP machines, we can't safely call 45 * OF once the kernel has been mapped to KERNELBASE. Therefore all 46 * OF calls should be done within prom_init(), and prom_init() 47 * and all routines called within it must be careful to relocate 48 * references as necessary. 49 * 50 * Note that the bss is cleared *after* prom_init runs, so we have 51 * to make sure that any static or extern variables it accesses 52 * are put in the data segment. 53 */ 54 55struct rtas_t rtas = { 56 lock: SPIN_LOCK_UNLOCKED 57}; 58 59extern unsigned long reloc_offset(void); 60 61void 62phys_call_rtas(int token, int nargs, int nret, ...) 63{ 64 va_list list; 65 unsigned long offset = reloc_offset(); 66 struct rtas_args *rtas = PTRRELOC(&(get_paca()->xRtas)); 67 int i; 68 69 rtas->token = token; 70 rtas->nargs = nargs; 71 rtas->nret = nret; 72 rtas->rets = (rtas_arg_t *)PTRRELOC(&(rtas->args[nargs])); 73 74 va_start(list, nret); 75 for (i = 0; i < nargs; i++) 76 rtas->args[i] = (rtas_arg_t)LONG_LSW(va_arg(list, ulong)); 77 va_end(list); 78 79 enter_rtas(rtas); 80} 81 82void 83phys_call_rtas_display_status(char c) 84{ 85 unsigned long offset = reloc_offset(); 86 struct rtas_args *rtas = PTRRELOC(&(get_paca()->xRtas)); 87 88 rtas->token = 10; 89 rtas->nargs = 1; 90 rtas->nret = 1; 91 rtas->rets = (rtas_arg_t *)PTRRELOC(&(rtas->args[1])); 92 rtas->args[0] = (int)c; 93 94 enter_rtas(rtas); 95} 96 97void 98call_rtas_display_status(char c) 99{ 100 struct rtas_args *rtas = &(get_paca()->xRtas); 101 102 rtas->token = 10; 103 rtas->nargs = 1; 104 rtas->nret = 1; 105 rtas->rets = (rtas_arg_t *)&(rtas->args[1]); 106 rtas->args[0] = (int)c; 107 108 enter_rtas((void *)__pa((unsigned long)rtas)); 109} 110 111__openfirmware 112int 113rtas_token(const char *service) 114{ 115 int *tokp; 116 if (rtas.dev == NULL) { 117 PPCDBG(PPCDBG_RTAS,"\tNo rtas device in device-tree...\n"); 118 return RTAS_UNKNOWN_SERVICE; 119 } 120 tokp = (int *) get_property(rtas.dev, service, NULL); 121 return tokp ? *tokp : RTAS_UNKNOWN_SERVICE; 122} 123 124__openfirmware 125long 126rtas_call(int token, int nargs, int nret, 127 unsigned long *outputs, ...) 128{ 129 va_list list; 130 int i; 131 unsigned long s; 132 struct rtas_args *rtas_args = &(get_paca()->xRtas); 133 134 PPCDBG(PPCDBG_RTAS, "Entering rtas_call\n"); 135 PPCDBG(PPCDBG_RTAS, "\ttoken = 0x%x\n", token); 136 PPCDBG(PPCDBG_RTAS, "\tnargs = %d\n", nargs); 137 PPCDBG(PPCDBG_RTAS, "\tnret = %d\n", nret); 138 PPCDBG(PPCDBG_RTAS, "\t&outputs = 0x%lx\n", outputs); 139 if (token == RTAS_UNKNOWN_SERVICE) 140 return -1; 141 142 rtas_args->token = token; 143 rtas_args->nargs = nargs; 144 rtas_args->nret = nret; 145 rtas_args->rets = (rtas_arg_t *)&(rtas_args->args[nargs]); 146 va_start(list, outputs); 147 for (i = 0; i < nargs; ++i) { 148 rtas_args->args[i] = (rtas_arg_t)LONG_LSW(va_arg(list, ulong)); 149 PPCDBG(PPCDBG_RTAS, "\tnarg[%d] = 0x%lx\n", i, rtas_args->args[i]); 150 } 151 va_end(list); 152 153 for (i = 0; i < nret; ++i) 154 rtas_args->rets[i] = 0; 155 156 spin_lock_irqsave(&rtas.lock, s); 157 PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n", 158 (void *)__pa((unsigned long)rtas_args)); 159 enter_rtas((void *)__pa((unsigned long)rtas_args)); 160 PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n"); 161 spin_unlock_irqrestore(&rtas.lock, s); 162 ifppcdebug(PPCDBG_RTAS) { 163 for(i=0; i < nret ;i++) 164 udbg_printf("\tnret[%d] = 0x%lx\n", i, (ulong)rtas_args->rets[i]); 165 } 166 167 if (nret > 1 && outputs != NULL) 168 for (i = 0; i < nret-1; ++i) 169 outputs[i] = rtas_args->rets[i+1]; 170 return (ulong)((nret > 0) ? rtas_args->rets[0] : 0); 171} 172 173#define FLASH_BLOCK_LIST_VERSION (1UL) 174static void 175rtas_flash_firmware(void) 176{ 177 unsigned long image_size; 178 struct flash_block_list *f, *next, *flist; 179 unsigned long rtas_block_list; 180 int i, status, update_token; 181 182 update_token = rtas_token("ibm,update-flash-64-and-reboot"); 183 if (update_token == RTAS_UNKNOWN_SERVICE) { 184 printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n"); 185 printk(KERN_ALERT "FLASH: firmware will not be flashed\n"); 186 return; 187 } 188 189 /* NOTE: the "first" block list is a global var with no data 190 * blocks in the kernel data segment. We do this because 191 * we want to ensure this block_list addr is under 4GB. 192 */ 193 rtas_firmware_flash_list.num_blocks = 0; 194 flist = (struct flash_block_list *)&rtas_firmware_flash_list; 195 rtas_block_list = virt_to_absolute((unsigned long)flist); 196 if (rtas_block_list >= (4UL << 20)) { 197 printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n"); 198 return; 199 } 200 201 printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n"); 202 /* Update the block_list in place. */ 203 image_size = 0; 204 for (f = flist; f; f = next) { 205 /* Translate data addrs to absolute */ 206 for (i = 0; i < f->num_blocks; i++) { 207 f->blocks[i].data = (char *)virt_to_absolute((unsigned long)f->blocks[i].data); 208 image_size += f->blocks[i].length; 209 } 210 next = f->next; 211 f->next = (struct flash_block_list *)virt_to_absolute((unsigned long)f->next); 212 /* make num_blocks into the version/length field */ 213 f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16); 214 } 215 216 printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size); 217 printk(KERN_ALERT "FLASH: performing flash and reboot\n"); 218 ppc_md.progress("Flashing \n", 0x0); 219 ppc_md.progress("Please Wait... ", 0x0); 220 printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n"); 221 status = rtas_call(update_token, 1, 1, NULL, rtas_block_list); 222 switch (status) { /* should only get "bad" status */ 223 case 0: 224 printk(KERN_ALERT "FLASH: success\n"); 225 break; 226 case -1: 227 printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n"); 228 break; 229 case -3: 230 printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n"); 231 break; 232 case -4: 233 printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n"); 234 break; 235 default: 236 printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status); 237 break; 238 } 239} 240 241void rtas_flash_bypass_warning(void) 242{ 243 printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n"); 244 printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n"); 245} 246 247 248void __chrp 249rtas_restart(char *cmd) 250{ 251 if (rtas_firmware_flash_list.next) 252 rtas_flash_firmware(); 253 254 printk("RTAS system-reboot returned %ld\n", 255 rtas_call(rtas_token("system-reboot"), 0, 1, NULL)); 256 for (;;); 257} 258 259void __chrp 260rtas_power_off(void) 261{ 262 if (rtas_firmware_flash_list.next) 263 rtas_flash_bypass_warning(); 264 /* allow power on only with power button press */ 265 printk("RTAS power-off returned %ld\n", 266 rtas_call(rtas_token("power-off"), 2, 1, NULL,0xffffffff,0xffffffff)); 267 for (;;); 268} 269 270void __chrp 271rtas_halt(void) 272{ 273 if (rtas_firmware_flash_list.next) 274 rtas_flash_bypass_warning(); 275 rtas_power_off(); 276} 277