inline int ipanic_func_write(fn_next next, void *data, int off, int total, int encrypt) { int errno = 0; size_t size; int start = off; struct ipanic_header *iheader = ipanic_header(); unsigned char *ipanic_buffer = (unsigned char *)(unsigned long)iheader->buf; size_t sz_ipanic_buffer = iheader->bufsize; size_t blksize = iheader->blksize; int many = total > iheader->bufsize; LOGV("off[%x], encrypt[%d]\n", off, encrypt); if (off & (blksize - 1)) return -2; /*invalid offset, not block aligned */ do { errno = next(data, ipanic_buffer, sz_ipanic_buffer); if (IS_ERR(ERR_PTR(errno))) break; size = (size_t) errno; if (size == 0) return (off - start); if ((off - start + size) > total) { LOGE("%s: data oversize(%zx>%x@%x)\n", __func__, off - start + size, total, start); errno = -EFBIG; break; } if (encrypt) ipanic_block_scramble(ipanic_buffer, size); if (size != sz_ipanic_buffer) { memset(ipanic_buffer + size, 0, sz_ipanic_buffer - size); } LOGV("%x@%x\n", size, off); if (ipanic_enable) errno = ipanic_write_size(ipanic_buffer, off, ALIGN(size, blksize)); else errno = -10; if (IS_ERR(ERR_PTR(errno))) break; off += size; if (many == 0) return size; } while (many); return errno; }
void ipanic_erase(void) { char *zero = kzalloc(PAGE_SIZE, GFP_KERNEL); ipanic_write_size(zero, 0, PAGE_SIZE); kfree(zero); }