/*===================================================================== */ void HvCall_writeLogBuffer(const void *buffer, u64 bufLen) { struct HvLpBufferList bufList; u64 bytesLeft = bufLen; u64 leftThisPage; u64 curPtr = virt_to_absolute((unsigned long) buffer); while (bytesLeft) { bufList.addr = curPtr; leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr; if (leftThisPage > bytesLeft) { bufList.len = bytesLeft; bytesLeft = 0; } else { bufList.len = leftThisPage; bytesLeft -= leftThisPage; } HvCall2(HvCallBaseWriteLogBuffer, virt_to_absolute((unsigned long) &bufList), bufList.len); curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE; } }
/*===================================================================== * Note that this call takes at MOST one page worth of data */ int HvCall_readLogBuffer(HvLpIndex lpIndex, void *buffer, u64 bufLen) { struct HvLpBufferList *bufList; u64 bytesLeft = bufLen; u64 leftThisPage; u64 curPtr = virt_to_absolute( (unsigned long) buffer ); u64 retVal; int npages; int i; npages = 0; while (bytesLeft) { npages++; leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr; if (leftThisPage > bytesLeft) bytesLeft = 0; else bytesLeft -= leftThisPage; curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE; } if (npages == 0) return 0; bufList = (struct HvLpBufferList *) kmalloc(npages * sizeof(struct HvLpBufferList), GFP_ATOMIC); bytesLeft = bufLen; curPtr = virt_to_absolute( (unsigned long) buffer ); for(i=0; i<npages; i++) { bufList[i].addr = curPtr; leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr; if (leftThisPage > bytesLeft) { bufList[i].len = bytesLeft; bytesLeft = 0; } else { bufList[i].len = leftThisPage; bytesLeft -= leftThisPage; } curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE; } retVal = HvCall3(HvCallBaseReadLogBuffer, lpIndex, virt_to_absolute((unsigned long)bufList), bufLen); kfree(bufList); return (int)retVal; }
static void tce_build_pSeriesLP(struct TceTable *tbl, long tcenum, unsigned long uaddr, int direction ) { u64 set_tce_rc; union Tce tce; PPCDBG(PPCDBG_TCE, "build_tce: uaddr = 0x%lx\n", uaddr); PPCDBG(PPCDBG_TCE, "\ttcenum = 0x%lx, tbl = 0x%lx, index=%lx\n", tcenum, tbl, tbl->index); tce.wholeTce = 0; tce.tceBits.rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT; tce.tceBits.readWrite = 1; if ( direction != PCI_DMA_TODEVICE ) tce.tceBits.pciWrite = 1; set_tce_rc = plpar_tce_put((u64)tbl->index, (u64)tcenum << 12, tce.wholeTce ); if(set_tce_rc) { printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", set_tce_rc); printk("\tindex = 0x%lx\n", (u64)tbl->index); printk("\ttcenum = 0x%lx\n", (u64)tcenum); printk("\ttce val = 0x%lx\n", tce.wholeTce ); } }
static void rtas_flash_firmware(void) { unsigned long image_size; struct flash_block_list *f, *next, *flist; unsigned long rtas_block_list; int i, status, update_token; 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_absolute((unsigned long)flist); if (rtas_block_list >= (4UL << 20)) { 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_absolute((unsigned long)f->blocks[i].data); image_size += f->blocks[i].length; } next = f->next; /* Don't translate final NULL pointer */ if (next) f->next = (struct flash_block_list *)virt_to_absolute((unsigned long)next); /* 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"); ppc_md.progress("Flashing \n", 0x0); ppc_md.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; } }