Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  printk.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
#include <linux/kernel.h>
#include <linux/stdarg.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <asm/stacktrace.h>
#include <asm/boot_data.h>
#include <asm/sections.h>
#include <asm/lowcore.h>
#include <asm/setup.h>
#include <asm/timex.h>
#include <asm/sclp.h>
#include <asm/uv.h>
#include "boot.h"

int boot_console_loglevel = CONFIG_CONSOLE_LOGLEVEL_DEFAULT;
bool boot_ignore_loglevel;
char __bootdata(boot_rb)[PAGE_SIZE * 2];
bool __bootdata(boot_earlyprintk);
size_t __bootdata(boot_rb_off);
char __bootdata(bootdebug_filter)[128];
bool __bootdata(bootdebug);

static void boot_rb_add(const char *str, size_t len)
{
 /* leave double '\0' in the end */
 size_t avail = sizeof(boot_rb) - boot_rb_off - 1;

 /* store strings separated by '\0' */
 if (len + 1 > avail)
  boot_rb_off = 0;
 avail = sizeof(boot_rb) - boot_rb_off - 1;
 strscpy(boot_rb + boot_rb_off, str, avail);
 boot_rb_off += len + 1;
}

static void print_rb_entry(const char *str)
{
 sclp_early_printk(printk_skip_level(str));
}

static bool debug_messages_printed(void)
{
 return boot_earlyprintk && (boot_ignore_loglevel || boot_console_loglevel > LOGLEVEL_DEBUG);
}

void boot_rb_dump(void)
{
 if (debug_messages_printed())
  return;
 sclp_early_printk("Boot messages ring buffer:\n");
 boot_rb_foreach(print_rb_entry);
}

const char hex_asc[] = "0123456789abcdef";

static char *as_hex(char *dst, unsigned long val, int pad)
{
 char *p = dst + max(pad, (int)__fls(val | 1) / 4 + 1);

 for (*p-- = '\0'; p >= dst; val >>= 4)
  *p-- = hex_asc[val & 0x0f];
 return dst;
}

#define MAX_NUMLEN 21
static char *as_dec(char *buf, unsigned long val, bool is_signed)
{
 bool negative = false;
 char *p = buf + MAX_NUMLEN;

 if (is_signed && (long)val < 0) {
  val = (val == LONG_MIN ? LONG_MIN : -(long)val);
  negative = true;
 }

 *--p = '\0';
 do {
  *--p = '0' + (val % 10);
  val /= 10;
 } while (val);

 if (negative)
  *--p = '-';
 return p;
}

static ssize_t strpad(char *dst, size_t dst_size, const char *src,
        int _pad, bool zero_pad, bool decimal)
{
 ssize_t len = strlen(src), pad = _pad;
 char *p = dst;

 if (max(len, abs(pad)) >= dst_size)
  return -E2BIG;

 if (pad > len) {
  if (decimal && zero_pad && *src == '-') {
   *p++ = '-';
   src++;
   len--;
   pad--;
  }
  memset(p, zero_pad ? '0' : ' ', pad - len);
  p += pad - len;
 }
 memcpy(p, src, len);
 p += len;
 if (pad < 0 && -pad > len) {
  memset(p, ' ', -pad - len);
  p += -pad - len;
 }
 *p = '\0';
 return p - dst;
}

static char *symstart(char *p)
{
 while (*p)
  p--;
 return p + 1;
}

static noinline char *findsym(unsigned long ip, unsigned short *off, unsigned short *len)
{
 /* symbol entries are in a form "10000 c4 startup\0" */
 char *a = _decompressor_syms_start;
 char *b = _decompressor_syms_end;
 unsigned long start;
 unsigned long size;
 char *pivot;
 char *endp;

 while (a < b) {
  pivot = symstart(a + (b - a) / 2);
  start = simple_strtoull(pivot, &endp, 16);
  size = simple_strtoull(endp + 1, &endp, 16);
  if (ip < start) {
   b = pivot;
   continue;
  }
  if (ip > start + size) {
   a = pivot + strlen(pivot) + 1;
   continue;
  }
  *off = ip - start;
  *len = size;
  return endp + 1;
 }
 return NULL;
}

#define MAX_SYMLEN 64
static noinline char *strsym(char *buf, void *ip)
{
 unsigned short off;
 unsigned short len;
 char *p;

 p = findsym((unsigned long)ip, &off, &len);
 if (p) {
  strscpy(buf, p, MAX_SYMLEN);
  /* reserve 15 bytes for offset/len in symbol+0x1234/0x1234 */
  p = buf + strnlen(buf, MAX_SYMLEN - 15);
  strscpy(p, "+0x", MAX_SYMLEN - (p - buf));
  as_hex(p + 3, off, 0);
  strcat(p, "/0x");
  as_hex(p + strlen(p), len, 0);
 } else {
  as_hex(buf, (unsigned long)ip, 16);
 }
 return buf;
}

static inline int printk_loglevel(const char *buf)
{
 if (buf[0] == KERN_SOH_ASCII && buf[1]) {
  switch (buf[1]) {
  case '0' ... '7':
   return buf[1] - '0';
  }
 }
 return MESSAGE_LOGLEVEL_DEFAULT;
}

static void boot_console_earlyprintk(const char *buf)
{
 int level = printk_loglevel(buf);

 /* always print emergency messages */
 if (level > LOGLEVEL_EMERG && !boot_earlyprintk)
  return;
 buf = printk_skip_level(buf);
 /* print debug messages only when bootdebug is enabled */
 if (level == LOGLEVEL_DEBUG && (!bootdebug || !bootdebug_filter_match(skip_timestamp(buf))))
  return;
 if (boot_ignore_loglevel || level < boot_console_loglevel)
  sclp_early_printk(buf);
}

static char *add_timestamp(char *buf)
{
#ifdef CONFIG_PRINTK_TIME
 unsigned long ns = tod_to_ns(__get_tod_clock_monotonic());
 char ts[MAX_NUMLEN];

 *buf++ = '[';
 buf += strpad(buf, MAX_NUMLEN, as_dec(ts, ns / NSEC_PER_SEC, 0), 5, 0, 0);
 *buf++ = '.';
 buf += strpad(buf, MAX_NUMLEN, as_dec(ts, (ns % NSEC_PER_SEC) / NSEC_PER_USEC, 0), 6, 1, 0);
 *buf++ = ']';
 *buf++ = ' ';
#endif
 return buf;
}

#define va_arg_len_type(args, lenmod, typemod)    \
 ((lenmod == 'l') ? va_arg(args, typemod long) :   \
  (lenmod == 'h') ? (typemod short)va_arg(args, typemod int) : \
  (lenmod == 'H') ? (typemod char)va_arg(args, typemod int) : \
  (lenmod == 'z') ? va_arg(args, typemod long) :   \
      va_arg(args, typemod int))

int boot_printk(const char *fmt, ...)
{
 char buf[1024] = { 0 };
 char *end = buf + sizeof(buf) - 1; /* make sure buf is 0 terminated */
 bool zero_pad, decimal;
 char *strval, *p = buf;
 char valbuf[MAX(MAX_SYMLEN, MAX_NUMLEN)];
 va_list args;
 char lenmod;
 ssize_t len;
 int pad;

 *p++ = KERN_SOH_ASCII;
 *p++ = printk_get_level(fmt) ?: '0' + MESSAGE_LOGLEVEL_DEFAULT;
 p = add_timestamp(p);
 fmt = printk_skip_level(fmt);

 va_start(args, fmt);
 for (; p < end && *fmt; fmt++) {
  if (*fmt != '%') {
   *p++ = *fmt;
   continue;
  }
  if (*++fmt == '%') {
   *p++ = '%';
   continue;
  }
  zero_pad = (*fmt == '0');
  pad = simple_strtol(fmt, (char **)&fmt, 10);
  lenmod = (*fmt == 'h' || *fmt == 'l' || *fmt == 'z') ? *fmt++ : 0;
  if (lenmod == 'h' && *fmt == 'h') {
   lenmod = 'H';
   fmt++;
  }
  decimal = false;
  switch (*fmt) {
  case 's':
   if (lenmod)
    goto out;
   strval = va_arg(args, char *);
   zero_pad = false;
   break;
  case 'p':
   if (*++fmt != 'S' || lenmod)
    goto out;
   strval = strsym(valbuf, va_arg(args, void *));
   zero_pad = false;
   break;
  case 'd':
  case 'i':
   strval = as_dec(valbuf, va_arg_len_type(args, lenmod, signed), 1);
   decimal = true;
   break;
  case 'u':
   strval = as_dec(valbuf, va_arg_len_type(args, lenmod, unsigned), 0);
   break;
  case 'x':
   strval = as_hex(valbuf, va_arg_len_type(args, lenmod, unsigned), 0);
   break;
  default:
   goto out;
  }
  len = strpad(p, end - p, strval, pad, zero_pad, decimal);
  if (len == -E2BIG)
   break;
  p += len;
 }
out:
 va_end(args);
 len = strlen(buf);
 if (len) {
  boot_rb_add(buf, len);
  boot_console_earlyprintk(buf);
 }
 return len;
}

Messung V0.5
C=98 H=84 G=91

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge