/* * Call the console drivers on a range of log_buf */ static void __call_console_drivers(unsigned start, unsigned end) { struct console *con; for_each_console(con) { if (exclusive_console && con != exclusive_console) continue; if ((con->flags & CON_ENABLED) && con->write && (cpu_online(smp_processor_id()) || (con->flags & CON_ANYTIME))) con->write(con, &LOG_BUF(start), end - start); } }
static void emit_log_char(char c) { LOG_BUF(log_end) = c; log_end++; if (log_end - log_start > log_buf_len) log_start = log_end - log_buf_len; if (log_end - con_start > log_buf_len) con_start = log_end - log_buf_len; if (logged_chars < log_buf_len) logged_chars++; emit_sec_log_char(c); }
static void emit_log_char(char c) { LOG_BUF(log_end) = c; log_end++; if (log_end - log_start > log_buf_len) log_start = log_end - log_buf_len; if (log_end - con_start > log_buf_len) con_start = log_end - log_buf_len; if (logged_chars < log_buf_len) logged_chars++; #ifdef CONFIG_DUMP_PREV_OOPS_MSG copy_char_to_oopsbuf(c); #endif }
static void emit_log_char(char c) { LOG_BUF(log_end) = c; log_end++; if (log_end - log_start > log_buf_len) log_start = log_end - log_buf_len; if (log_end - con_start > log_buf_len) con_start = log_end - log_buf_len; if (logged_chars < log_buf_len) logged_chars++; //early_putc(c, c); // JBH ^^^^ }
PureOmxBufferData::PureOmxBufferData(const PureOmxPlatformLayer& aPlatformLayer, const OMX_PARAM_PORTDEFINITIONTYPE& aPortDef) : BufferData(nullptr) , mPlatformLayer(aPlatformLayer) , mPortDef(aPortDef) { LOG_BUF(""); if (ShouldUseEGLImage()) { // TODO LOG_BUF("OMX_UseEGLImage() seems available but using it isn't implemented yet."); } OMX_ERRORTYPE err; err = OMX_AllocateBuffer(mPlatformLayer.GetComponent(), &mBuffer, mPortDef.nPortIndex, this, mPortDef.nBufferSize); if (err != OMX_ErrorNone) { LOG_BUF("Failed to allocate the buffer!: 0x%08x", err); } }
/* * Call the console drivers on a range of log_buf */ static void __call_console_drivers(unsigned start, unsigned end) { struct console *con; for_each_console(con) { if ((con->flags & CON_ENABLED) && con->write && console_atomic_safe(con) && (cpu_online(raw_smp_processor_id()) || (con->flags & CON_ANYTIME))) { set_printk_might_sleep(1); con->write(con, &LOG_BUF(start), end - start); set_printk_might_sleep(0); } } }
static void emit_log_char(char c) { LOG_BUF(log_end) = c; #ifdef CONFIG_HAS_EARLYSUSPEND if(suspend_process_going) IRAM_LOG_BUF(log_end) = c; #endif log_end++; if (log_end - log_start > log_buf_len) log_start = log_end - log_buf_len; if (log_end - con_start > log_buf_len) con_start = log_end - log_buf_len; if (logged_chars < log_buf_len) logged_chars++; }
UINT8 writeChunkOnLogBlockDuringGC(const UINT32 dataLpn, const UINT32 dataChunkOffset, const UINT32 chunkOffsetInBuf, const UINT32 bufAddr) { /* Need this function because during GC can't use the global variables, because those might be related to an outstanding write (which triggered the GC) */ UINT32 bank = chooseNewBank(); uart_print("writeChunkOnLogBlockDuringGC, bank="); uart_print_int(bank); uart_print(" dataLpn="); uart_print_int(dataLpn); uart_print(", dataChunkOffset="); uart_print_int(dataChunkOffset); uart_print("\r\n"); int sectOffset = dataChunkOffset * SECTORS_PER_CHUNK; UINT32 src = bufAddr + (chunkOffsetInBuf * BYTES_PER_CHUNK); UINT32 dst = LOG_BUF(bank) + (chunkPtr[bank] * BYTES_PER_CHUNK); // base address of the destination chunk waitBusyBank(bank); mem_copy(dst, src, BYTES_PER_CHUNK); updateDramBufMetadataDuringGc(bank, dataLpn, sectOffset); updateChunkPtrDuringGC(bank); return 0; }
static void emit_log_char(char c) { LOG_BUF(log_end) = c; log_end++; if (log_end - log_start > log_buf_len) log_start = log_end - log_buf_len; if (log_end - con_start > log_buf_len) con_start = log_end - log_buf_len; if (logged_chars < log_buf_len) logged_chars++; //Pochun_TKxxx_20101123_Begin #ifdef CONFIG_CCI_KLOG_COLLECTOR cklc_append_kernel_raw_char(c); #endif //Pochun_TKxxx_20101123_End }
static void writePartialChunkWhenOldIsInOWBuf(UINT32 nSectsToWrite, UINT32 oldChunkAddr) { uart_print("writePartialChunkWhenOldIsInOWBuf\r\n"); // Old Chunk Location UINT32 oldBank = ChunkToBank(oldChunkAddr); UINT32 oldSectOffset = ChunkToSectOffset(oldChunkAddr); // Buffers UINT32 dstWBufStart = LOG_BUF(bank_) + (chunkPtr[bank_] * BYTES_PER_CHUNK); // base address of the destination chunk UINT32 srcOWBufStart = OW_LOG_BUF(oldBank)+(oldSectOffset*BYTES_PER_SECTOR); // location of old chunk // Sizes waitBusyBank(bank_); mem_copy(dstWBufStart, srcOWBufStart, BYTES_PER_CHUNK); // First copy old data from OW Buf UINT32 startOffsetWrite = (sectOffset_ % SECTORS_PER_CHUNK) * BYTES_PER_SECTOR; UINT32 srcSataBufStart = WR_BUF_PTR(g_ftl_write_buf_id)+((sectOffset_ / SECTORS_PER_CHUNK)*BYTES_PER_CHUNK); mem_copy(dstWBufStart+startOffsetWrite, srcSataBufStart+startOffsetWrite, nSectsToWrite*BYTES_PER_SECTOR); // Then copy new data from SATA Buf }
/* * Write out chars from start to end - 1 inclusive */ static void _call_console_drivers(unsigned start, unsigned end, int msg_log_level) { trace_console(&LOG_BUF(0), start, end, log_buf_len); if ((msg_log_level < console_loglevel || ignore_loglevel) && console_drivers && start != end) { if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) { /* wrapped write */ __call_console_drivers(start & LOG_BUF_MASK, log_buf_len); __call_console_drivers(0, end & LOG_BUF_MASK); } else { __call_console_drivers(start, end); } } }
static void writePartialChunkWhenOldIsInWBuf(UINT32 nSectsToWrite, UINT32 oldChunkAddr) { uart_print("writePartialChunkWhenOldIsInWBuf\r\n"); // Old Chunk Location UINT32 oldBank = ChunkToBank(oldChunkAddr); UINT32 oldSectOffset = ChunkToSectOffset(oldChunkAddr); // Buffers UINT32 dstWBufStart = LOG_BUF(oldBank)+(oldSectOffset*BYTES_PER_SECTOR); // location of old chunk UINT32 srcSataBufStart = WR_BUF_PTR(g_ftl_write_buf_id)+((sectOffset_ / SECTORS_PER_CHUNK)*BYTES_PER_CHUNK); // Sizes UINT32 startOffsetWrite = (sectOffset_ % SECTORS_PER_CHUNK) * BYTES_PER_SECTOR; //waitBusyBank(bank_); waitBusyBank(oldBank); mem_copy(dstWBufStart+startOffsetWrite, srcSataBufStart+startOffsetWrite, nSectsToWrite*BYTES_PER_SECTOR); #if MeasureDramAbsorb uart_print_level_1("WRDRAM "); uart_print_level_1_int(nSectsToWrite); uart_print_level_1("\r\n"); #endif }
int log_buf_copy2(char *dest, int dest_len, int log_copy_start, int log_copy_end) { bool took_lock = false; int count; if (!oops_in_progress) { raw_spin_lock_irq(&logbuf_lock); took_lock = true; } for (count = 0; (log_copy_start != log_end) && (log_copy_start != log_copy_end) && (count < dest_len); log_copy_start++) { dest[count++] = LOG_BUF(log_copy_start); } if (took_lock) raw_spin_unlock_irq(&logbuf_lock); return count; }
static void emit_log_char(char c,int prt_to_con) { LOG_BUF(log_end) = c; log_end++; if (log_end - log_start > log_buf_len) log_start = log_end - log_buf_len; if (log_end - con_start > log_buf_len) con_start = log_end - log_buf_len; if (logged_chars < log_buf_len) logged_chars++; #if defined(CONFIG_PRINTK) || defined(CONFIG_PANIC_PRINTK) if (prt_to_con) { PRT_BUF(prt_end) = c; prt_end++; if (prt_end - prt_start > __LOG_BUF_LEN) prt_start = prt_end - __LOG_BUF_LEN; } #endif }
/* * Call the console drivers, asking them to write out * log_buf[start] to log_buf[end - 1]. * The console_sem must be held. */ static void call_console_drivers(unsigned long start, unsigned long end) { unsigned long cur_index, start_print; static int msg_level = -1; if (((long)(start - end)) > 0) BUG(); cur_index = start; start_print = start; while (cur_index != end) { if ( msg_level < 0 && ((end - cur_index) > 2) && LOG_BUF(cur_index + 0) == '<' && LOG_BUF(cur_index + 1) >= '0' && LOG_BUF(cur_index + 1) <= '7' && LOG_BUF(cur_index + 2) == '>') { msg_level = LOG_BUF(cur_index + 1) - '0'; cur_index += 3; start_print = cur_index; } while (cur_index != end) { char c = LOG_BUF(cur_index); cur_index++; if (c == '\n') { if (msg_level < 0) { /* * printk() has already given us loglevel tags in * the buffer. This code is here in case the * log buffer has wrapped right round and scribbled * on those tags */ msg_level = default_message_loglevel; } _call_console_drivers(start_print, cur_index, msg_level); msg_level = -1; start_print = cur_index; break; } } } _call_console_drivers(start_print, end, msg_level); }
static void overwriteChunkOldInWBuf(UINT32 chunkAddr) { //uart_print_level_1("23 "); /* Question: is it better to copy the ow buf or to overwrite in place in w buf? * Current implementation: copy to the ow buf, because probably will be overwritten again in the future. */ uart_print("overwriteChunkOldInWBuf\r\n"); chooseNewBank_(); UINT32 nSectsToWrite = (((sectOffset_ % SECTORS_PER_CHUNK) + remainingSects_) < SECTORS_PER_CHUNK) ? remainingSects_ : (SECTORS_PER_CHUNK - (sectOffset_ % SECTORS_PER_CHUNK)); UINT32 srcBank = ChunkToBank(chunkAddr); UINT32 srcChunkIdx = ChunkToChunkOffset(chunkAddr); UINT32 startOffsetOverwrite = (sectOffset_ % SECTORS_PER_CHUNK) * BYTES_PER_SECTOR; UINT32 endOffsetOverwrite = ((sectOffset_ % SECTORS_PER_CHUNK) + nSectsToWrite) * BYTES_PER_SECTOR; UINT32 wBufAddr = LOG_BUF(srcBank) + srcChunkIdx*BYTES_PER_CHUNK; UINT32 owBufAddr = OW_LOG_BUF(bank_) + owChunkPtr[bank_] * BYTES_PER_CHUNK; UINT32 sataBufAddr = WR_BUF_PTR(g_ftl_write_buf_id)+(sectOffset_*BYTES_PER_SECTOR); UINT32 leftHoleSize = startOffsetOverwrite; UINT32 rightHoleSize = BYTES_PER_CHUNK - endOffsetOverwrite; waitBusyBank(bank_); // (Fabio) probably should wait. In contrast to overwriteChunkOldInOwBuf, here we are writing to a new chunk in ow buf, thus it might be that a previous operation involving ow buf is in flight mem_copy(owBufAddr + leftHoleSize, sataBufAddr, nSectsToWrite*BYTES_PER_SECTOR); if(leftHoleSize > 0) { uart_print("copy left hole\r\n"); mem_copy(owBufAddr, wBufAddr, leftHoleSize); // copy left hole } if(rightHoleSize > 0) { uart_print("copy right hole\r\n"); mem_copy(owBufAddr+endOffsetOverwrite, wBufAddr+endOffsetOverwrite, rightHoleSize); // copy right hole } logBufMeta[srcBank].dataLpn[srcChunkIdx]=INVALID; // invalidate in w buf updateOwDramBufMetadata(); updateOwChunkPtr(); sectOffset_ += nSectsToWrite; remainingSects_ -= nSectsToWrite; #if MeasureDramAbsorb uart_print_level_1("OWDRAM "); uart_print_level_1_int(nSectsToWrite); uart_print_level_1("\r\n"); #endif }
int dev_read_kmsg(char __user *buf, int len) { int error = -EINVAL; unsigned i; char c; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; if (!access_ok(VERIFY_WRITE, buf, len)) { error = -EFAULT; goto out; } error = wait_event_interruptible(dev_wait, (dev_start - log_end)); if (error) goto out; i = 0; raw_spin_lock_irq(&logbuf_lock); while (!error && (dev_start != log_end) && i < len) { c = LOG_BUF(dev_start); dev_start++; raw_spin_unlock_irq(&logbuf_lock); error = __put_user(c,buf); buf++; i++; cond_resched(); raw_spin_lock_irq(&logbuf_lock); } raw_spin_unlock_irq(&logbuf_lock); if (!error) error = i; out: return error; }
int do_syslog(int type, char __user *buf, int len, bool from_file) { unsigned i, j, limit, count; int do_clear = 0; char c; int error; error = check_syslog_permissions(type, from_file); if (error) goto out; error = security_syslog(type); if (error) return error; switch (type) { case SYSLOG_ACTION_CLOSE: break; case SYSLOG_ACTION_OPEN: break; case SYSLOG_ACTION_READ: error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; if (!access_ok(VERIFY_WRITE, buf, len)) { error = -EFAULT; goto out; } error = wait_event_interruptible(log_wait, (log_start - log_end)); if (error) goto out; i = 0; raw_spin_lock_irq(&logbuf_lock); while (!error && (log_start != log_end) && i < len) { c = LOG_BUF(log_start); log_start++; raw_spin_unlock_irq(&logbuf_lock); error = __put_user(c,buf); buf++; i++; cond_resched(); raw_spin_lock_irq(&logbuf_lock); } raw_spin_unlock_irq(&logbuf_lock); if (!error) error = i; break; case SYSLOG_ACTION_READ_CLEAR: do_clear = 1; case SYSLOG_ACTION_READ_ALL: error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; if (!access_ok(VERIFY_WRITE, buf, len)) { error = -EFAULT; goto out; } count = len; if (count > log_buf_len) count = log_buf_len; raw_spin_lock_irq(&logbuf_lock); if (count > logged_chars) count = logged_chars; if (do_clear) logged_chars = 0; limit = log_end; for (i = 0; i < count && !error; i++) { j = limit-1-i; if (j + log_buf_len < log_end) break; c = LOG_BUF(j); raw_spin_unlock_irq(&logbuf_lock); error = __put_user(c,&buf[count-1-i]); cond_resched(); raw_spin_lock_irq(&logbuf_lock); } raw_spin_unlock_irq(&logbuf_lock); if (error) break; error = i; if (i != count) { int offset = count-error; for (i = 0; i < error; i++) { if (__get_user(c,&buf[i+offset]) || __put_user(c,&buf[i])) { error = -EFAULT; break; } cond_resched(); } } break; case SYSLOG_ACTION_CLEAR: logged_chars = 0; break; case SYSLOG_ACTION_CONSOLE_OFF: if (saved_console_loglevel == -1) saved_console_loglevel = console_loglevel; console_loglevel = minimum_console_loglevel; break; case SYSLOG_ACTION_CONSOLE_ON: if (saved_console_loglevel != -1) { console_loglevel = saved_console_loglevel; saved_console_loglevel = -1; } break; case SYSLOG_ACTION_CONSOLE_LEVEL: error = -EINVAL; if (len < 1 || len > 8) goto out; if (len < minimum_console_loglevel) len = minimum_console_loglevel; console_loglevel = len; saved_console_loglevel = -1; error = 0; break; case SYSLOG_ACTION_SIZE_UNREAD: error = log_end - log_start; break; case SYSLOG_ACTION_SIZE_BUFFER: error = log_buf_len; break; default: error = -EINVAL; break; } out: return error; }
/* * Commands to do_syslog: * * 0 -- Close the log. Currently a NOP. * 1 -- Open the log. Currently a NOP. * 2 -- Read from the log. * 3 -- Read all messages remaining in the ring buffer. * 4 -- Read and clear all messages remaining in the ring buffer * 5 -- Clear ring buffer. * 6 -- Disable printk's to console * 7 -- Enable printk's to console * 8 -- Set level of messages printed to console * 9 -- Return number of unread characters in the log buffer */ int do_syslog(int type, char * buf, int len) { unsigned long i, j, limit, count; int do_clear = 0; char c; int error = 0; switch (type) { case 0: /* Close log */ break; case 1: /* Open log */ break; case 2: /* Read from log */ error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; error = verify_area(VERIFY_WRITE,buf,len); if (error) goto out; error = wait_event_interruptible(log_wait, (log_start - log_end)); if (error) goto out; i = 0; spin_lock_irq(&logbuf_lock); while ((log_start != log_end) && i < len) { c = LOG_BUF(log_start); log_start++; spin_unlock_irq(&logbuf_lock); __put_user(c,buf); buf++; i++; spin_lock_irq(&logbuf_lock); } spin_unlock_irq(&logbuf_lock); error = i; break; case 4: /* Read/clear last kernel messages */ do_clear = 1; /* FALL THRU */ case 3: /* Read last kernel messages */ error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; error = verify_area(VERIFY_WRITE,buf,len); if (error) goto out; count = len; if (count > LOG_BUF_LEN) count = LOG_BUF_LEN; spin_lock_irq(&logbuf_lock); if (count > logged_chars) count = logged_chars; if (do_clear) logged_chars = 0; limit = log_end; /* * __put_user() could sleep, and while we sleep * printk() could overwrite the messages * we try to copy to user space. Therefore * the messages are copied in reverse. <manfreds> */ for(i=0;i < count;i++) { j = limit-1-i; if (j+LOG_BUF_LEN < log_end) break; c = LOG_BUF(j); spin_unlock_irq(&logbuf_lock); __put_user(c,&buf[count-1-i]); spin_lock_irq(&logbuf_lock); } spin_unlock_irq(&logbuf_lock); error = i; if(i != count) { int offset = count-error; /* buffer overflow during copy, correct user buffer. */ for(i=0;i<error;i++) { __get_user(c,&buf[i+offset]); __put_user(c,&buf[i]); } } break; case 5: /* Clear ring buffer */ spin_lock_irq(&logbuf_lock); logged_chars = 0; spin_unlock_irq(&logbuf_lock); break; case 6: /* Disable logging to console */ spin_lock_irq(&logbuf_lock); console_loglevel = minimum_console_loglevel; spin_unlock_irq(&logbuf_lock); break; case 7: /* Enable logging to console */ spin_lock_irq(&logbuf_lock); console_loglevel = default_console_loglevel; spin_unlock_irq(&logbuf_lock); break; case 8: /* Set level of messages printed to console */ error = -EINVAL; if (len < 1 || len > 8) goto out; if (len < minimum_console_loglevel) len = minimum_console_loglevel; spin_lock_irq(&logbuf_lock); console_loglevel = len; spin_unlock_irq(&logbuf_lock); error = 0; break; case 9: /* Number of chars in the log buffer */ spin_lock_irq(&logbuf_lock); error = log_end - log_start; spin_unlock_irq(&logbuf_lock); break; case 20: #ifdef CONFIG_EVLOG error = verify_area(VERIFY_WRITE, buf, len); if (error) { goto out; } error = evl_kbufread(buf, len); #else error = -EIO; #endif break; #if 0 case 21: #ifdef CONFIG_EVLOG error = verify_area(VERIFY_READ, buf, len); if (error) { goto out; } error = evl_uwrite_buf(buf, len); #else error = -EIO; #endif break; #endif default: error = -EINVAL; break; } out: return error; }
PureOmxBufferData::~PureOmxBufferData() { LOG_BUF(""); ReleaseBuffer(); }
int md32_aee_dump(char *buf) { volatile unsigned int *reg; char *ptr = buf; ssize_t i, len; unsigned int log_start_idx; unsigned int log_end_idx; unsigned int log_buf_max_len; unsigned char *__log_buf = (unsigned char *)(MD32_DTCM + md32_log_buf_addr); if(!buf) return 0; printk("md32_aee_dump\n"); ptr += sprintf(ptr, "md32 status = 0x%08x\n", md32_aee_status.status); ptr += sprintf(ptr, "md32 pc=0x%08x, r14=0x%08x, r15=0x%08x\n", md32_aee_status.pc, md32_aee_status.r14, md32_aee_status.r15); ptr += sprintf(ptr, "md32 to host irq = 0x%08x\n", md32_aee_status.m2h_irq); ptr += sprintf(ptr, "host to md32 irq = 0x%08x\n", HOST_TO_MD32_REG); ptr += sprintf(ptr, "wdt en=%d, count=0x%08x\n", (MD32_WDT_REG & 0x10000000) ? 1 : 0, (MD32_WDT_REG & 0xFFFFF)); /*dump all md32 regs*/ for(reg = (volatile unsigned int *)MD32_BASE; reg < (MD32_BASE + 0xA8); reg++) { //if(!(reg & 0xF)) { ptr += sprintf(ptr, "\n"); ptr += sprintf(ptr, "[0x%p] ", reg); } ptr += sprintf(ptr, "0x%08x ", *reg); } ptr += sprintf(ptr, "\n"); #define LOG_BUF_MASK (log_buf_max_len-1) #define LOG_BUF(idx) (__log_buf[(idx) & LOG_BUF_MASK]) log_start_idx = readl((void __iomem *)(MD32_DTCM + md32_log_start_idx_addr)); log_end_idx = readl((void __iomem *)(MD32_DTCM + md32_log_end_idx_addr)); log_buf_max_len = readl((void __iomem *)(MD32_DTCM + md32_log_buf_len_addr)); ptr += sprintf(ptr, "log_buf_addr = 0x%08x\n", (unsigned int)md32_log_buf_addr); ptr += sprintf(ptr, "log_start_idx = %u\n", log_start_idx); ptr += sprintf(ptr, "log_end_idx = %u\n", log_end_idx); ptr += sprintf(ptr, "log_buf_max_len = %u\n", log_buf_max_len); ptr += sprintf(ptr, "<<md32 log buf start>>\n"); len = (log_buf_max_len > 0x1000) ? 0x1000 : log_buf_max_len; i = 0; while((log_start_idx != log_end_idx) && i < len) { ptr += sprintf(ptr, "%c", LOG_BUF(log_start_idx)); log_start_idx++; i++; } ptr += sprintf(ptr, "<<md32 log buf end>>\n"); printk("md32_aee_dump end\n"); return ptr - buf; }
int do_syslog(int type, char __user *buf, int len, bool from_file) { unsigned i, j, limit, count; int do_clear = 0; char c; int error = 0; /* * If this is from /proc/kmsg we only do the capabilities checks * at open time. */ if (type == SYSLOG_ACTION_OPEN || !from_file) { if (dmesg_restrict && !capable(CAP_SYS_ADMIN)) return -EPERM; if ((type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER) && !capable(CAP_SYS_ADMIN)) return -EPERM; } error = security_syslog(type); if (error) return error; switch (type) { case SYSLOG_ACTION_CLOSE: /* Close log */ break; case SYSLOG_ACTION_OPEN: /* Open log */ break; case SYSLOG_ACTION_READ: /* Read from log */ error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; if (!access_ok(VERIFY_WRITE, buf, len)) { error = -EFAULT; goto out; } error = wait_event_interruptible(log_wait, (log_start - log_end)); if (error) goto out; i = 0; spin_lock_irq(&logbuf_lock); while (!error && (log_start != log_end) && i < len) { c = LOG_BUF(log_start); log_start++; spin_unlock_irq(&logbuf_lock); error = __put_user(c,buf); buf++; i++; cond_resched(); spin_lock_irq(&logbuf_lock); } spin_unlock_irq(&logbuf_lock); if (!error) error = i; break; /* Read/clear last kernel messages */ case SYSLOG_ACTION_READ_CLEAR: do_clear = 1; /* FALL THRU */ /* Read last kernel messages */ case SYSLOG_ACTION_READ_ALL: error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; if (!access_ok(VERIFY_WRITE, buf, len)) { error = -EFAULT; goto out; } count = len; if (count > log_buf_len) count = log_buf_len; spin_lock_irq(&logbuf_lock); if (count > logged_chars) count = logged_chars; if (do_clear) logged_chars = 0; limit = log_end; /* * __put_user() could sleep, and while we sleep * printk() could overwrite the messages * we try to copy to user space. Therefore * the messages are copied in reverse. <manfreds> */ for (i = 0; i < count && !error; i++) { j = limit-1-i; if (j + log_buf_len < log_end) break; c = LOG_BUF(j); spin_unlock_irq(&logbuf_lock); error = __put_user(c,&buf[count-1-i]); cond_resched(); spin_lock_irq(&logbuf_lock); } spin_unlock_irq(&logbuf_lock); if (error) break; error = i; if (i != count) { int offset = count-error; /* buffer overflow during copy, correct user buffer. */ for (i = 0; i < error; i++) { if (__get_user(c,&buf[i+offset]) || __put_user(c,&buf[i])) { error = -EFAULT; break; } cond_resched(); } } break; /* Clear ring buffer */ case SYSLOG_ACTION_CLEAR: logged_chars = 0; break; /* Disable logging to console */ case SYSLOG_ACTION_CONSOLE_OFF: if (saved_console_loglevel == -1) saved_console_loglevel = console_loglevel; console_loglevel = minimum_console_loglevel; break; /* Enable logging to console */ case SYSLOG_ACTION_CONSOLE_ON: if (saved_console_loglevel != -1) { console_loglevel = saved_console_loglevel; saved_console_loglevel = -1; } break; /* Set level of messages printed to console */ case SYSLOG_ACTION_CONSOLE_LEVEL: error = -EINVAL; if (len < 1 || len > 8) goto out; if (len < minimum_console_loglevel) len = minimum_console_loglevel; console_loglevel = len; /* Implicitly re-enable logging to console */ saved_console_loglevel = -1; error = 0; break; /* Number of chars in the log buffer */ case SYSLOG_ACTION_SIZE_UNREAD: error = log_end - log_start; break; /* Size of the log buffer */ case SYSLOG_ACTION_SIZE_BUFFER: error = log_buf_len; break; default: error = -EINVAL; break; } out: return error; }
/* * Commands to do_syslog: * * 0 -- Close the log. Currently a NOP. * 1 -- Open the log. Currently a NOP. * 2 -- Read from the log. * 3 -- Read all messages remaining in the ring buffer. * 4 -- Read and clear all messages remaining in the ring buffer * 5 -- Clear ring buffer. * 6 -- Disable printk's to console * 7 -- Enable printk's to console * 8 -- Set level of messages printed to console * 9 -- Return number of unread characters in the log buffer * 10 -- Return size of the log buffer */ int do_syslog(int type, char __user *buf, int len) { unsigned i, j, limit, count; int do_clear = 0; char c; int error = 0; error = security_syslog(type); if (error) return error; switch (type) { case 0: /* Close log */ break; case 1: /* Open log */ break; case 2: /* Read from log */ error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; if (!access_ok(VERIFY_WRITE, buf, len)) { error = -EFAULT; goto out; } error = wait_event_interruptible(log_wait, (log_start - log_end)); if (error) goto out; i = 0; spin_lock_irq(&logbuf_lock); while (!error && (log_start != log_end) && i < len) { c = LOG_BUF(log_start); log_start++; spin_unlock_irq(&logbuf_lock); error = __put_user(c,buf); buf++; i++; cond_resched(); spin_lock_irq(&logbuf_lock); } spin_unlock_irq(&logbuf_lock); if (!error) error = i; break; case 4: /* Read/clear last kernel messages */ do_clear = 1; /* FALL THRU */ case 3: /* Read last kernel messages */ error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; if (!access_ok(VERIFY_WRITE, buf, len)) { error = -EFAULT; goto out; } count = len; if (count > log_buf_len) count = log_buf_len; spin_lock_irq(&logbuf_lock); if (count > logged_chars) count = logged_chars; if (do_clear) logged_chars = 0; limit = log_end; /* * __put_user() could sleep, and while we sleep * printk() could overwrite the messages * we try to copy to user space. Therefore * the messages are copied in reverse. <manfreds> */ for (i = 0; i < count && !error; i++) { j = limit-1-i; if (j + log_buf_len < log_end) break; c = LOG_BUF(j); spin_unlock_irq(&logbuf_lock); error = __put_user(c,&buf[count-1-i]); cond_resched(); spin_lock_irq(&logbuf_lock); } spin_unlock_irq(&logbuf_lock); if (error) break; error = i; if (i != count) { int offset = count-error; /* buffer overflow during copy, correct user buffer. */ for (i = 0; i < error; i++) { if (__get_user(c,&buf[i+offset]) || __put_user(c,&buf[i])) { error = -EFAULT; break; } cond_resched(); } } break; case 5: /* Clear ring buffer */ logged_chars = 0; break; case 6: /* Disable logging to console */ console_loglevel = minimum_console_loglevel; break; case 7: /* Enable logging to console */ console_loglevel = default_console_loglevel; break; case 8: /* Set level of messages printed to console */ error = -EINVAL; if (len < 1 || len > 8) goto out; if (len < minimum_console_loglevel) len = minimum_console_loglevel; console_loglevel = len; error = 0; break; case 9: /* Number of chars in the log buffer */ error = log_end - log_start; break; case 10: /* Size of the log buffer */ error = log_buf_len; break; default: error = -EINVAL; break; } out: return error; }
void __init setup_ext_logbuff(void) { #ifdef CONFIG_ALT_LB_LOCATION volatile logbuff_t *log; #else logbuff_t *log; #endif unsigned long flags, space, start, dest_idx, offset; if (setup_ext_logbuff_mem(&log, &log_buf)) { printk("Failed to setup external logbuffer - ignoring it\n"); return; } /* When no properly setup buffer is found, reset pointers */ if (log->tag != LOGBUFF_MAGIC) { log->start = log->end = 0; printk("Properly setup external logbuffer not found - using it anyway!\n"); } spin_lock_irqsave(&logbuf_lock, flags); /* Limit pointers */ if (log->end - log->start > LOGBUFF_LEN) log->start = log->end - LOGBUFF_LEN; space = LOGBUFF_LEN - (log->end - log->start); if (log_end - log_start > space) log_start = log_end - space; if (log_end - con_start > space) con_start = log_end - space; log->chars = logged_chars + log->end - log->start; if (log->chars > LOGBUFF_LEN) log->chars = LOGBUFF_LEN; /* Chars passed by the boot loader will appear after those we already have in the local buffer */ offset = log->start - log_end; start = min((long)con_start, (long)log_start); dest_idx = start + offset; while (start != log_end) { log_buf[dest_idx & (LOGBUFF_LEN - 1)] = LOG_BUF(start); start++; dest_idx++; } log->start = log_start + offset; log->con = con_start + offset; /* Switch to the external log buffer */ ext_log_start = &log->start; ext_con_start = &log->con; ext_log_end = &log->end; ext_logged_chars = &log->chars; log_buf_len = LOGBUFF_LEN; spin_unlock_irqrestore(&logbuf_lock, flags); printk("Kernel logbuffer at 0x%p\n", log_buf); }