cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

printf.c (2972B)


      1/*
      2 * Copyright (C) 2015 Virtual Open Systems SAS
      3 * Author: Alexander Spyridakis <a.spyridakis@virtualopensystems.com>
      4 *
      5 * printf based on implementation by Kevin Wolf <kwolf@redhat.com>
      6 *
      7 * This program is free software; you can redistribute it and/or modify
      8 * it under the terms of the GNU General Public License version 2 as
      9 * published by the Free Software Foundation.
     10 *
     11 * SPDX-License-Identifier: GPL-2.0-only
     12 */
     13
     14#include "minilib.h"
     15
     16typedef __builtin_va_list   va_list;
     17#define va_start(ap, X)     __builtin_va_start(ap, X)
     18#define va_arg(ap, type)    __builtin_va_arg(ap, type)
     19#define va_end(ap)          __builtin_va_end(ap)
     20
     21static void print_str(char *s)
     22{
     23    while (*s) {
     24        __sys_outc(*s++);
     25    }
     26}
     27
     28static void print_num(unsigned long long value, int base)
     29{
     30    char digits[] = "0123456789abcdef";
     31    char buf[32];
     32    int i = sizeof(buf) - 2, j;
     33
     34    /* Set the buffer to 0. See problem of before. */
     35    for (j = 0; j < 32; j++) {
     36        buf[j] = 0;
     37    }
     38
     39    do {
     40        buf[i--] = digits[value % base];
     41        value /= base;
     42    } while (value);
     43
     44    print_str(&buf[i + 1]);
     45}
     46
     47void ml_printf(const char *fmt, ...)
     48{
     49    va_list ap;
     50    char *str;
     51    int base;
     52    int has_long;
     53    int alt_form;
     54    unsigned long long val;
     55
     56    va_start(ap, fmt);
     57
     58    for (; *fmt; fmt++) {
     59        if (*fmt != '%') {
     60            __sys_outc(*fmt);
     61            continue;
     62        }
     63        fmt++;
     64
     65        if (*fmt == '#') {
     66            fmt++;
     67            alt_form = 1;
     68        } else {
     69            alt_form = 0;
     70        }
     71
     72        if (*fmt == 'l') {
     73            fmt++;
     74            if (*fmt == 'l') {
     75                fmt++;
     76                has_long = 2;
     77            } else {
     78                has_long = 1;
     79            }
     80        } else {
     81            has_long = 0;
     82        }
     83
     84        switch (*fmt) {
     85        case 'x':
     86        case 'p':
     87            base = 16;
     88            goto convert_number;
     89        case 'd':
     90        case 'i':
     91        case 'u':
     92            base = 10;
     93            goto convert_number;
     94        case 'o':
     95            base = 8;
     96            goto convert_number;
     97
     98        convert_number:
     99            switch (has_long) {
    100            case 0:
    101                val = va_arg(ap, unsigned int);
    102                break;
    103            case 1:
    104                val = va_arg(ap, unsigned long);
    105                break;
    106            case 2:
    107                val = va_arg(ap, unsigned long long);
    108                break;
    109            }
    110
    111            if (alt_form && base == 16) {
    112                print_str("0x");
    113            }
    114
    115            print_num(val, base);
    116            break;
    117
    118        case 's':
    119            str = va_arg(ap, char*);
    120            print_str(str);
    121            break;
    122        case 'c':
    123            __sys_outc(va_arg(ap, int));
    124            break;
    125        case '%':
    126            __sys_outc(*fmt);
    127            break;
    128        default:
    129            __sys_outc('%');
    130            __sys_outc(*fmt);
    131            break;
    132        }
    133    }
    134
    135    va_end(ap);
    136}