forked from lolo859/vystem
887 lines
26 KiB
C
887 lines
26 KiB
C
// SPDX-License-Identifier: MPL-2.0
|
|
#include "std/stdlib.h"
|
|
#include "devs/apic/lapic.h"
|
|
#include "memory/ring.h"
|
|
#include "cpu/serial.h"
|
|
sh_bool are_rings_buffer_setup=SH_FALSE;
|
|
sh_ring_RING_BUFFER_HEADER *ring_buffer_array=SH_NULLPTR;
|
|
sh_SPIN_LOCK serial_lock=SH_LOCK();
|
|
SH_STATUS sh_print_setup_ring_buffers_per_ap(sh_conf_BOOT_CONFIG *boot_config) {
|
|
if (are_rings_buffer_setup==SH_TRUE || ring_buffer_array!=SH_NULLPTR || boot_config==SH_NULLPTR) return SH_STATUS_UNAVAILABLE;
|
|
sh_uint64 cpu_count=0;
|
|
sh_lapic_DEVICE **lapic_dev_array=sh_lapic_get_by_apic_id_array();
|
|
sh_uint64 max_lapic_id=sh_lapic_get_max_apic_id();
|
|
for (sh_iter64 i=0;i<max_lapic_id+1;i++) {
|
|
sh_lapic_DEVICE *lapic_dev=lapic_dev_array[i];
|
|
if (lapic_dev==SH_NULLPTR) continue;
|
|
cpu_count++;
|
|
}
|
|
ring_buffer_array=(sh_ring_RING_BUFFER_HEADER*)sh_malloc(sizeof(sh_ring_RING_BUFFER_HEADER)*cpu_count);
|
|
if (!ring_buffer_array) return SH_STATUS_ERROR_NULLPTR_RETURNED;
|
|
sh_mem_set_8((sh_uint8*)ring_buffer_array,0x0,sizeof(sh_ring_RING_BUFFER_HEADER)*cpu_count);
|
|
sh_uint64 log_ring_size_ap=boot_config->log_ring_size/cpu_count;
|
|
if (log_ring_size_ap<4) log_ring_size_ap=4;
|
|
for (sh_iter64 i=0;i<cpu_count;i++) {
|
|
ring_buffer_array[i].data_start=sh_malloc(log_ring_size_ap*SH_PAGE_SIZE);
|
|
if (ring_buffer_array[i].data_start==SH_NULLPTR) return SH_STATUS_ERROR_NULLPTR_RETURNED;
|
|
ring_buffer_array[i].buffer_bytes_size=(sh_uint32)log_ring_size_ap*SH_PAGE_SIZE;
|
|
}
|
|
are_rings_buffer_setup=SH_TRUE;
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_print_byte(sh_uint8 byte);
|
|
SH_STATUS sh_print_int8(sh_int8 n);
|
|
SH_STATUS sh_print_int16(sh_int16 n);
|
|
SH_STATUS sh_print_int32(sh_int32 n);
|
|
SH_STATUS sh_print_int64(sh_int64 n);
|
|
SH_STATUS sh_print_uint8(sh_uint8 n);
|
|
SH_STATUS sh_print_uint16(sh_uint16 n);
|
|
SH_STATUS sh_print_uint32(sh_uint32 n);
|
|
SH_STATUS sh_print_uint64(sh_uint64 n);
|
|
SH_STATUS sh_print_uint8_hex(sh_uint8 n);
|
|
SH_STATUS sh_print_uint16_hex(sh_uint16 n);
|
|
SH_STATUS sh_print_uint32_hex(sh_uint32 n);
|
|
SH_STATUS sh_print_uint64_hex(sh_uint64 n);
|
|
SH_STATUS sh_print_uint64_hex_fixed(sh_uint64 n);
|
|
SH_STATUS sh_print_double(double value);
|
|
SH_STATUS sh_print_flush();
|
|
SH_STATUS sh_print_flush() {
|
|
char *text_to_flush=sh_malloc(sh_smp_gs_base()->per_cpu->bytes_outputed);
|
|
if (!text_to_flush) return SH_STATUS_ERROR_NULLPTR_RETURNED;
|
|
sh_spin_lock(&serial_lock);
|
|
SH_STATUS status=sh_ring_read_bytes(&ring_buffer_array[sh_smp_gs_base()->per_cpu->cpu_id],sh_smp_gs_base()->per_cpu->bytes_outputed,text_to_flush);
|
|
if (sh_status_error(status)) {
|
|
sh_spin_unlock(&serial_lock);
|
|
return status;
|
|
}
|
|
sh_log_string(text_to_flush);
|
|
sh_spin_unlock(&serial_lock);
|
|
sh_free(text_to_flush);
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_print_byte(sh_uint8 byte) {
|
|
if (!are_rings_buffer_setup) {
|
|
sh_log_byte(byte);
|
|
return SH_STATUS_SUCCESS;
|
|
} else {
|
|
SH_STATUS status=sh_ring_write_byte(&ring_buffer_array[sh_smp_gs_base()->per_cpu->cpu_id],byte);
|
|
if (sh_status_error(status)) return status;
|
|
sh_smp_gs_base()->per_cpu->bytes_outputed++;
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
}
|
|
SH_STATUS sh_print_int8(sh_int8 n) {
|
|
return sh_print_int64((sh_int64)n);
|
|
}
|
|
SH_STATUS sh_print_int16(sh_int16 n) {
|
|
return sh_print_int64((sh_int64)n);
|
|
}
|
|
SH_STATUS sh_print_int32(sh_int32 n) {
|
|
return sh_print_int64((sh_int64)n);
|
|
}
|
|
SH_STATUS sh_print_int64(sh_int64 n) {
|
|
sh_uint64 absolute_val;
|
|
if (n<0) {
|
|
sh_print_byte('-');
|
|
absolute_val=(sh_uint64)(-(n+1))+1;
|
|
} else {
|
|
absolute_val=(sh_uint64)n;
|
|
}
|
|
return sh_print_uint64(absolute_val);
|
|
}
|
|
SH_STATUS sh_print_uint8(sh_uint8 n) {
|
|
return sh_print_uint64((sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_print_uint16(sh_uint16 n) {
|
|
return sh_print_uint64((sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_print_uint32(sh_uint32 n) {
|
|
return sh_print_uint64((sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_print_uint64(sh_uint64 n) {
|
|
char buf[20];
|
|
sh_uint32 i=0;
|
|
if (n==0) {
|
|
sh_print_byte('0');
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
while (n>0) {
|
|
buf[i++]='0'+(sh_int8)(n%10);
|
|
n/=10;
|
|
}
|
|
while (i--) {
|
|
sh_print_byte((sh_uint8)buf[i]);
|
|
}
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_print_uint8_hex(sh_uint8 n) {
|
|
return sh_print_uint64_hex((sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_print_uint16_hex(sh_uint16 n) {
|
|
return sh_print_uint64_hex((sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_print_uint32_hex(sh_uint32 n) {
|
|
return sh_print_uint64_hex((sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_print_uint64_hex(sh_uint64 n) {
|
|
char buf[16];
|
|
sh_uint32 i=0;
|
|
const char hex_digits[]="0123456789ABCDEF";
|
|
if (n==0) {
|
|
sh_print_byte('0');
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
while (n>0) {
|
|
buf[i++]=hex_digits[n & 0xF];
|
|
n>>=4;
|
|
}
|
|
while (i--) {
|
|
sh_print_byte((sh_uint8)buf[i]);
|
|
}
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_print_uint64_hex_fixed(sh_uint64 n) {
|
|
const char hex_digits[]="0123456789ABCDEF";
|
|
for (sh_int8 i=15;i>=0;i--) {
|
|
sh_uint8 nibble=(sh_uint8)((n>>(i*4))&0xF);
|
|
sh_print_byte((sh_uint8)hex_digits[nibble]);
|
|
}
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_print_double(double value) {
|
|
if (value<0) {
|
|
sh_print_byte('-');
|
|
value=-value;
|
|
}
|
|
sh_uint64 integer_part=(sh_uint64)value;
|
|
double fractional_part=value-(double)integer_part;
|
|
SH_STATUS status=sh_print_uint64(integer_part);
|
|
if (status!=SH_STATUS_SUCCESS) return status;
|
|
sh_print_byte('.');
|
|
for (sh_iter64 i=0;i<6;i++) {
|
|
fractional_part*=10.0;
|
|
sh_uint64 digit=(sh_uint64)fractional_part;
|
|
sh_print_byte('0'+(sh_uint8)digit);
|
|
fractional_part-=(double)digit;
|
|
}
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_print(sh_log_OUTPUT_TYPE output_type,char *text) {
|
|
if (text==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER;
|
|
sh_tsc_TSC_VALUE tsc_value=sh_tsc_get_kernel_current_tsc();
|
|
if (!sh_log_output_type_valid(output_type)) return SH_STATUS_INVALID_PARAMETER;
|
|
if (output_type<sh_log_get_log_level()) {
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
sh_smp_gs_base()->per_cpu->bytes_outputed=0;
|
|
sh_asm_cli();
|
|
char *intro="[Shelter:";
|
|
while (*intro) {
|
|
sh_print_byte((sh_uint8)*intro++);
|
|
}
|
|
sh_print_uint64(sh_smp_gs_base()->per_cpu->cpu_id);
|
|
sh_print_byte('@');
|
|
char* type=SH_NULLPTR;
|
|
if (output_type==SH_DEBUG) {
|
|
type="Debug] ";
|
|
} else if (output_type==SH_LOG) {
|
|
type="Log] ";
|
|
} else if (output_type==SH_WARNING) {
|
|
type="Warning] ";
|
|
} else if (output_type==SH_ERROR) {
|
|
type="Error] ";
|
|
} else if (output_type==SH_CRITICAL) {
|
|
type="Critical] ";
|
|
} else if (output_type==SH_FATAL) {
|
|
type="Fatal] ";
|
|
} else if (output_type==SH_TEST) {
|
|
type="Test] ";
|
|
} else if (output_type==SH_FAULT) {
|
|
type="Fault] ";
|
|
}
|
|
while (*type) {
|
|
sh_print_byte((sh_uint8)*type++);
|
|
}
|
|
sh_print_uint64(tsc_value);
|
|
char *transition=" : ";
|
|
while (*transition) {
|
|
sh_print_byte((sh_uint8)*transition++);
|
|
}
|
|
while (*text) {
|
|
sh_print_byte((sh_uint8)*text++);
|
|
}
|
|
SH_STATUS status=sh_print_flush();
|
|
if (sh_status_error(status)) return status;
|
|
sh_asm_sti();
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_printf(sh_log_OUTPUT_TYPE output_type,char* format,...) {
|
|
if (format==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER;
|
|
sh_tsc_TSC_VALUE tsc_value=sh_tsc_get_kernel_current_tsc();
|
|
if (!sh_log_output_type_valid(output_type)) return SH_STATUS_INVALID_PARAMETER;
|
|
if (output_type<sh_log_get_log_level()) {
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
sh_smp_gs_base()->per_cpu->bytes_outputed=0;
|
|
sh_asm_cli();
|
|
char *intro="[Shelter:";
|
|
while (*intro) {
|
|
sh_print_byte((sh_uint8)*intro++);
|
|
}
|
|
sh_print_uint64(sh_smp_gs_base()->per_cpu->cpu_id);
|
|
sh_print_byte('@');
|
|
char* type=SH_NULLPTR;
|
|
if (output_type==SH_DEBUG) {
|
|
type="Debug] ";
|
|
} else if (output_type==SH_LOG) {
|
|
type="Log] ";
|
|
} else if (output_type==SH_WARNING) {
|
|
type="Warning] ";
|
|
} else if (output_type==SH_ERROR) {
|
|
type="Error] ";
|
|
} else if (output_type==SH_CRITICAL) {
|
|
type="Critical] ";
|
|
} else if (output_type==SH_FATAL) {
|
|
type="Fatal] ";
|
|
} else if (output_type==SH_TEST) {
|
|
type="Test] ";
|
|
} else if (output_type==SH_FAULT) {
|
|
type="Fault] ";
|
|
}
|
|
while (*type) {
|
|
sh_print_byte((sh_uint8)*type++);
|
|
}
|
|
sh_print_uint64(tsc_value);
|
|
char *transition=" : ";
|
|
while (*transition) {
|
|
sh_print_byte((sh_uint8)*transition++);
|
|
}
|
|
va_list args;
|
|
va_start(args,format);
|
|
for (const char *p=format;*p!='\0';p++) {
|
|
if (*p!='%') {
|
|
sh_print_byte((sh_uint8)*p);
|
|
continue;
|
|
}
|
|
p++;
|
|
switch (*p) {
|
|
case 's': {
|
|
char *s=va_arg(args,char *);
|
|
while (*s) {
|
|
sh_print_byte((sh_uint8)*s++);
|
|
}
|
|
break;
|
|
}
|
|
case 'd': {
|
|
double s=va_arg(args,double);
|
|
sh_print_double(s);
|
|
break;
|
|
}
|
|
case '1': {
|
|
if (p[1]=='u') {
|
|
sh_print_uint8((sh_uint8)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='s') {
|
|
sh_print_int8((sh_int8)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='U') {
|
|
sh_print_uint8_hex((sh_uint8)va_arg(args,int));
|
|
p++;
|
|
}
|
|
break;
|
|
}
|
|
case '2': {
|
|
if (p[1]=='u') {
|
|
sh_print_uint16((sh_uint16)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='s') {
|
|
sh_print_int16((sh_int16)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='U') {
|
|
sh_print_uint16_hex((sh_uint16)va_arg(args,int));
|
|
p++;
|
|
}
|
|
break;
|
|
}
|
|
case '4': {
|
|
if (p[1]=='u') {
|
|
sh_print_uint32((sh_uint32)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='s') {
|
|
sh_print_int32((sh_int32)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='U') {
|
|
sh_print_uint32_hex((sh_uint32)va_arg(args,int));
|
|
p++;
|
|
}
|
|
break;
|
|
}
|
|
case '8': {
|
|
if (p[1]=='u') {
|
|
sh_print_uint64(va_arg(args,unsigned long long));
|
|
p++;
|
|
} else if (p[1]=='s') {
|
|
sh_print_int64(va_arg(args,long long));
|
|
p++;
|
|
} else if (p[1]=='U') {
|
|
sh_print_uint64_hex(va_arg(args,unsigned long long));
|
|
p++;
|
|
}
|
|
break;
|
|
}
|
|
case 'x': {
|
|
sh_uint64 x=va_arg(args,sh_uint64);
|
|
sh_print_uint64_hex_fixed(x);
|
|
break;
|
|
}
|
|
case 'c': {
|
|
sh_print_byte((sh_uint8)va_arg(args,int));
|
|
break;
|
|
}
|
|
case '%': {
|
|
sh_print_byte('%');
|
|
break;
|
|
}
|
|
default:
|
|
sh_print_byte((sh_uint8)*p);
|
|
break;
|
|
}
|
|
}
|
|
va_end(args);
|
|
SH_STATUS status=sh_print_flush();
|
|
if (sh_status_error(status)) return status;
|
|
sh_asm_sti();
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_print_ibyte(sh_uint8 byte);
|
|
SH_STATUS sh_print_iint8(sh_int8 n);
|
|
SH_STATUS sh_print_iint16(sh_int16 n);
|
|
SH_STATUS sh_print_iint32(sh_int32 n);
|
|
SH_STATUS sh_print_iint64(sh_int64 n);
|
|
SH_STATUS sh_print_iuint8(sh_uint8 n);
|
|
SH_STATUS sh_print_iuint16(sh_uint16 n);
|
|
SH_STATUS sh_print_iuint32(sh_uint32 n);
|
|
SH_STATUS sh_print_iuint64(sh_uint64 n);
|
|
SH_STATUS sh_print_iuint8_hex(sh_uint8 n);
|
|
SH_STATUS sh_print_iuint16_hex(sh_uint16 n);
|
|
SH_STATUS sh_print_iuint32_hex(sh_uint32 n);
|
|
SH_STATUS sh_print_iuint64_hex(sh_uint64 n);
|
|
SH_STATUS sh_print_iuint64_hex_fixed(sh_uint64 n);
|
|
SH_STATUS sh_print_idouble(double value);
|
|
SH_STATUS sh_print_ibyte(sh_uint8 byte) {
|
|
sh_serial_send_byte(byte);
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_print_iint8(sh_int8 n) {
|
|
return sh_print_iint64((sh_int64)n);
|
|
}
|
|
SH_STATUS sh_print_iint16(sh_int16 n) {
|
|
return sh_print_iint64((sh_int64)n);
|
|
}
|
|
SH_STATUS sh_print_iint32(sh_int32 n) {
|
|
return sh_print_iint64((sh_int64)n);
|
|
}
|
|
SH_STATUS sh_print_iint64(sh_int64 n) {
|
|
sh_uint64 absolute_val;
|
|
if (n<0) {
|
|
sh_print_ibyte('-');
|
|
absolute_val=(sh_uint64)(-(n+1))+1;
|
|
} else {
|
|
absolute_val=(sh_uint64)n;
|
|
}
|
|
return sh_print_iuint64(absolute_val);
|
|
}
|
|
SH_STATUS sh_print_iuint8(sh_uint8 n) {
|
|
return sh_print_iuint64((sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_print_iuint16(sh_uint16 n) {
|
|
return sh_print_iuint64((sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_print_iuint32(sh_uint32 n) {
|
|
return sh_print_iuint64((sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_print_iuint64(sh_uint64 n) {
|
|
char buf[20];
|
|
sh_uint32 i=0;
|
|
if (n==0) {
|
|
sh_print_ibyte('0');
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
while (n>0) {
|
|
buf[i++]='0'+(sh_int8)(n%10);
|
|
n/=10;
|
|
}
|
|
while (i--) {
|
|
sh_print_ibyte((sh_uint8)buf[i]);
|
|
}
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_print_iuint8_hex(sh_uint8 n) {
|
|
return sh_print_iuint64_hex((sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_print_iuint16_hex(sh_uint16 n) {
|
|
return sh_print_iuint64_hex((sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_print_iuint32_hex(sh_uint32 n) {
|
|
return sh_print_iuint64_hex((sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_print_iuint64_hex(sh_uint64 n) {
|
|
char buf[16];
|
|
sh_uint32 i=0;
|
|
const char hex_digits[]="0123456789ABCDEF";
|
|
if (n==0) {
|
|
sh_print_ibyte('0');
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
while (n>0) {
|
|
buf[i++]=hex_digits[n & 0xF];
|
|
n>>=4;
|
|
}
|
|
while (i--) {
|
|
sh_print_ibyte((sh_uint8)buf[i]);
|
|
}
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_print_iuint64_hex_fixed(sh_uint64 n) {
|
|
const char hex_digits[]="0123456789ABCDEF";
|
|
for (sh_int8 i=15;i>=0;i--) {
|
|
sh_uint8 nibble=(sh_uint8)((n>>(i*4))&0xF);
|
|
sh_print_ibyte((sh_uint8)hex_digits[nibble]);
|
|
}
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_print_idouble(double value) {
|
|
if (value<0) {
|
|
sh_print_ibyte('-');
|
|
value=-value;
|
|
}
|
|
sh_uint64 integer_part=(sh_uint64)value;
|
|
double fractional_part=value-(double)integer_part;
|
|
SH_STATUS status=sh_print_iuint64(integer_part);
|
|
if (status!=SH_STATUS_SUCCESS) return status;
|
|
sh_print_ibyte('.');
|
|
for (sh_iter64 i=0;i<6;i++) {
|
|
fractional_part*=10.0;
|
|
sh_uint64 digit=(sh_uint64)fractional_part;
|
|
sh_print_ibyte('0'+(sh_uint8)digit);
|
|
fractional_part-=(double)digit;
|
|
}
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_iprint(sh_log_OUTPUT_TYPE output_type,char *text) {
|
|
if (text==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER;
|
|
sh_tsc_TSC_VALUE tsc_value=sh_tsc_get_kernel_current_tsc();
|
|
if (!sh_log_output_type_valid(output_type)) return SH_STATUS_INVALID_PARAMETER;
|
|
if (output_type<sh_log_get_log_level()) {
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
sh_bool was_locked_by_me=SH_FALSE;
|
|
if (sh_spin_wholock(&serial_lock)==sh_smp_gs_base()->lapic_id) was_locked_by_me=SH_TRUE;
|
|
if (!was_locked_by_me) {
|
|
sh_spin_lock(&serial_lock);
|
|
}
|
|
char *intro="[Shelter:";
|
|
while (*intro) {
|
|
sh_print_ibyte((sh_uint8)*intro++);
|
|
}
|
|
sh_print_iuint64(sh_smp_gs_base()->per_cpu->cpu_id);
|
|
sh_print_ibyte('@');
|
|
char* type=SH_NULLPTR;
|
|
if (output_type==SH_DEBUG) {
|
|
type="Debug] ";
|
|
} else if (output_type==SH_LOG) {
|
|
type="Log] ";
|
|
} else if (output_type==SH_WARNING) {
|
|
type="Warning] ";
|
|
} else if (output_type==SH_ERROR) {
|
|
type="Error] ";
|
|
} else if (output_type==SH_CRITICAL) {
|
|
type="Critical] ";
|
|
} else if (output_type==SH_FATAL) {
|
|
type="Fatal] ";
|
|
} else if (output_type==SH_TEST) {
|
|
type="Test] ";
|
|
} else if (output_type==SH_FAULT) {
|
|
type="Fault] ";
|
|
}
|
|
while (*type) {
|
|
sh_print_ibyte((sh_uint8)*type++);
|
|
}
|
|
sh_print_iuint64(tsc_value);
|
|
char *transition=" : ";
|
|
while (*transition) {
|
|
sh_print_ibyte((sh_uint8)*transition++);
|
|
}
|
|
while (*text) {
|
|
sh_print_ibyte((sh_uint8)*text++);
|
|
}
|
|
if (!was_locked_by_me) sh_spin_unlock(&serial_lock);
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_iprintf(sh_log_OUTPUT_TYPE output_type,char* format,...) {
|
|
if (format==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER;
|
|
sh_tsc_TSC_VALUE tsc_value=sh_tsc_get_kernel_current_tsc();
|
|
if (!sh_log_output_type_valid(output_type)) return SH_STATUS_INVALID_PARAMETER;
|
|
if (output_type<sh_log_get_log_level()) {
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
sh_bool was_locked_by_me=SH_FALSE;
|
|
if (sh_spin_wholock(&serial_lock)==sh_smp_gs_base()->lapic_id) was_locked_by_me=SH_TRUE;
|
|
if (!was_locked_by_me) {
|
|
sh_spin_lock(&serial_lock);
|
|
}
|
|
char *intro="[Shelter:";
|
|
while (*intro) {
|
|
sh_print_ibyte((sh_uint8)*intro++);
|
|
}
|
|
sh_print_iuint64(sh_smp_gs_base()->per_cpu->cpu_id);
|
|
sh_print_ibyte('@');
|
|
char* type=SH_NULLPTR;
|
|
if (output_type==SH_DEBUG) {
|
|
type="Debug] ";
|
|
} else if (output_type==SH_LOG) {
|
|
type="Log] ";
|
|
} else if (output_type==SH_WARNING) {
|
|
type="Warning] ";
|
|
} else if (output_type==SH_ERROR) {
|
|
type="Error] ";
|
|
} else if (output_type==SH_CRITICAL) {
|
|
type="Critical] ";
|
|
} else if (output_type==SH_FATAL) {
|
|
type="Fatal] ";
|
|
} else if (output_type==SH_TEST) {
|
|
type="Test] ";
|
|
} else if (output_type==SH_FAULT) {
|
|
type="Fault] ";
|
|
}
|
|
while (*type) {
|
|
sh_print_ibyte((sh_uint8)*type++);
|
|
}
|
|
sh_print_iuint64(tsc_value);
|
|
char *transition=" : ";
|
|
while (*transition) {
|
|
sh_print_ibyte((sh_uint8)*transition++);
|
|
}
|
|
va_list args;
|
|
va_start(args,format);
|
|
for (const char *p=format;*p!='\0';p++) {
|
|
if (*p!='%') {
|
|
sh_print_ibyte((sh_uint8)*p);
|
|
continue;
|
|
}
|
|
p++;
|
|
switch (*p) {
|
|
case 's': {
|
|
char *s=va_arg(args,char *);
|
|
while (*s) {
|
|
sh_print_ibyte((sh_uint8)*s++);
|
|
}
|
|
break;
|
|
}
|
|
case 'd': {
|
|
double s=va_arg(args,double);
|
|
sh_print_idouble(s);
|
|
break;
|
|
}
|
|
case '1': {
|
|
if (p[1]=='u') {
|
|
sh_print_iuint8((sh_uint8)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='s') {
|
|
sh_print_iint8((sh_int8)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='U') {
|
|
sh_print_iuint8_hex((sh_uint8)va_arg(args,int));
|
|
p++;
|
|
}
|
|
break;
|
|
}
|
|
case '2': {
|
|
if (p[1]=='u') {
|
|
sh_print_iuint16((sh_uint16)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='s') {
|
|
sh_print_iint16((sh_int16)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='U') {
|
|
sh_print_iuint16_hex((sh_uint16)va_arg(args,int));
|
|
p++;
|
|
}
|
|
break;
|
|
}
|
|
case '4': {
|
|
if (p[1]=='u') {
|
|
sh_print_iuint32((sh_uint32)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='s') {
|
|
sh_print_iint32((sh_int32)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='U') {
|
|
sh_print_iuint32_hex((sh_uint32)va_arg(args,int));
|
|
p++;
|
|
}
|
|
break;
|
|
}
|
|
case '8': {
|
|
if (p[1]=='u') {
|
|
sh_print_iuint64(va_arg(args,unsigned long long));
|
|
p++;
|
|
} else if (p[1]=='s') {
|
|
sh_print_iint64(va_arg(args,long long));
|
|
p++;
|
|
} else if (p[1]=='U') {
|
|
sh_print_iuint64_hex(va_arg(args,unsigned long long));
|
|
p++;
|
|
}
|
|
break;
|
|
}
|
|
case 'x': {
|
|
sh_uint64 x=va_arg(args,sh_uint64);
|
|
sh_print_iuint64_hex_fixed(x);
|
|
break;
|
|
}
|
|
case 'c': {
|
|
sh_print_ibyte((sh_uint8)va_arg(args,int));
|
|
break;
|
|
}
|
|
case '%': {
|
|
sh_print_ibyte('%');
|
|
break;
|
|
}
|
|
default:
|
|
sh_print_ibyte((sh_uint8)*p);
|
|
break;
|
|
}
|
|
}
|
|
va_end(args);
|
|
if (!was_locked_by_me) sh_spin_unlock(&serial_lock);
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
typedef struct sh_sprint_WRITER {
|
|
sh_uint8 *out;
|
|
sh_uint8 *end;
|
|
} sh_sprint_WRITER;
|
|
static inline SH_STATUS sh_sprint_byte(sh_sprint_WRITER *w,sh_uint8 c) {
|
|
if(w->out>=w->end) return SH_STATUS_TOO_MUCH_DATA;
|
|
*w->out++=c;
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_sprint_int8(sh_sprint_WRITER *w,sh_int8 n);
|
|
SH_STATUS sh_sprint_int16(sh_sprint_WRITER *w,sh_int16 n);
|
|
SH_STATUS sh_sprint_int32(sh_sprint_WRITER *w,sh_int32 n);
|
|
SH_STATUS sh_sprint_int64(sh_sprint_WRITER *w,sh_int64 n);
|
|
SH_STATUS sh_sprint_uint8(sh_sprint_WRITER *w,sh_uint8 n);
|
|
SH_STATUS sh_sprint_uint16(sh_sprint_WRITER *w,sh_uint16 n);
|
|
SH_STATUS sh_sprint_uint32(sh_sprint_WRITER *w,sh_uint32 n);
|
|
SH_STATUS sh_sprint_uint64(sh_sprint_WRITER *w,sh_uint64 n);
|
|
SH_STATUS sh_sprint_uint8_hex(sh_sprint_WRITER *w,sh_uint8 n);
|
|
SH_STATUS sh_sprint_uint16_hex(sh_sprint_WRITER *w,sh_uint16 n);
|
|
SH_STATUS sh_sprint_uint32_hex(sh_sprint_WRITER *w,sh_uint32 n);
|
|
SH_STATUS sh_sprint_uint64_hex(sh_sprint_WRITER *w,sh_uint64 n);
|
|
SH_STATUS sh_sprint_uint64_hex_fixed(sh_sprint_WRITER *w,sh_uint64 n);
|
|
SH_STATUS sh_sprint_double(sh_sprint_WRITER *w,double value);
|
|
SH_STATUS sh_sprint_int8(sh_sprint_WRITER *w,sh_int8 n) {
|
|
return sh_sprint_int64(w,(sh_int64)n);
|
|
}
|
|
SH_STATUS sh_sprint_int16(sh_sprint_WRITER *w,sh_int16 n) {
|
|
return sh_sprint_int64(w,(sh_int64)n);
|
|
}
|
|
SH_STATUS sh_sprint_int32(sh_sprint_WRITER *w,sh_int32 n) {
|
|
return sh_sprint_int64(w,(sh_int64)n);
|
|
}
|
|
SH_STATUS sh_sprint_int64(sh_sprint_WRITER *w,sh_int64 n) {
|
|
sh_uint64 absolute_val;
|
|
if (n<0) {
|
|
SH_STATUS status=sh_sprint_byte(w,'-');
|
|
if (sh_status_error(status)) return status;
|
|
absolute_val=(sh_uint64)(-(n+1))+1;
|
|
} else {
|
|
absolute_val=(sh_uint64)n;
|
|
}
|
|
return sh_sprint_uint64(w,absolute_val);
|
|
}
|
|
SH_STATUS sh_sprint_uint8(sh_sprint_WRITER *w,sh_uint8 n) {
|
|
return sh_sprint_uint64(w,(sh_int64)n);
|
|
}
|
|
SH_STATUS sh_sprint_uint16(sh_sprint_WRITER *w,sh_uint16 n) {
|
|
return sh_sprint_uint64(w,(sh_int64)n);
|
|
}
|
|
SH_STATUS sh_sprint_uint32(sh_sprint_WRITER *w,sh_uint32 n) {
|
|
return sh_sprint_uint64(w,(sh_int64)n);
|
|
}
|
|
SH_STATUS sh_sprint_uint64(sh_sprint_WRITER *w,sh_uint64 n) {
|
|
char buf[20];
|
|
sh_uint32 i=0;
|
|
if (n==0) return sh_sprint_byte(w,'0');
|
|
while (n>0) {
|
|
buf[i++]='0'+(sh_int8)(n%10);
|
|
n/=10;
|
|
}
|
|
while (i--) {
|
|
SH_STATUS status=sh_sprint_byte(w,(sh_uint8)buf[i]);
|
|
if (sh_status_error(status)) return status;
|
|
}
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_sprint_uint8_hex(sh_sprint_WRITER *w,sh_uint8 n) {
|
|
return sh_sprint_uint64_hex(w,(sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_sprint_uint16_hex(sh_sprint_WRITER *w,sh_uint16 n) {
|
|
return sh_sprint_uint64_hex(w,(sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_sprint_uint32_hex(sh_sprint_WRITER *w,sh_uint32 n) {
|
|
return sh_sprint_uint64_hex(w,(sh_uint64)n);
|
|
}
|
|
SH_STATUS sh_sprint_uint64_hex(sh_sprint_WRITER *w,sh_uint64 n) {
|
|
char buf[16];
|
|
sh_uint32 i=0;
|
|
const char hex_digits[]="0123456789ABCDEF";
|
|
if (n==0) return sh_sprint_byte(w,'0');
|
|
while (n>0) {
|
|
buf[i++]=hex_digits[n & 0xF];
|
|
n>>=4;
|
|
}
|
|
while (i--) {
|
|
SH_STATUS status=sh_sprint_byte(w,(sh_uint8)buf[i]);
|
|
if (sh_status_error(status)) return status;
|
|
}
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_sprint_uint64_hex_fixed(sh_sprint_WRITER *w,sh_uint64 n) {
|
|
const char hex[]="0123456789ABCDEF";
|
|
for (sh_int8 i=15;i>=0;i--) {
|
|
char c=hex[(n>>(i*4))&0xF];
|
|
SH_STATUS status=sh_sprint_byte(w,(sh_uint8)c);
|
|
if (sh_status_error(status)) return status;
|
|
}
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_sprint_double(sh_sprint_WRITER *w,double value) {
|
|
SH_STATUS status;
|
|
if(value<0) {
|
|
status=sh_sprint_byte(w,'-');
|
|
if (sh_status_error(status)) return status;
|
|
value= -value;
|
|
}
|
|
sh_uint64 int_part=(sh_uint64)value;
|
|
double frac=value-(double)int_part;
|
|
status=sh_sprint_uint64(w,int_part);
|
|
if (sh_status_error(status)) return status;
|
|
status=sh_sprint_byte(w,'.');
|
|
if (sh_status_error(status)) return status;
|
|
for(sh_iter64 i=0;i<6;i++) {
|
|
frac*=10.0;
|
|
sh_uint64 d=(sh_uint64)frac;
|
|
status=sh_sprint_byte(w,(sh_uint8)'0'+(sh_uint8)d);
|
|
if (sh_status_error(status)) return status;
|
|
frac-=(double)d;
|
|
}
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_sprintf(char *output_string,sh_uint64 output_len,char *format,...) {
|
|
if (format==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER;
|
|
sh_asm_cli();
|
|
sh_sprint_WRITER w={
|
|
.out=(sh_uint8*)output_string,
|
|
.end=(sh_uint8*)output_string+output_len
|
|
};
|
|
va_list args;
|
|
va_start(args,format);
|
|
for (const char *p=format;*p!='\0';p++) {
|
|
if (*p!='%') {
|
|
sh_sprint_byte(&w,(sh_uint8)*p);
|
|
continue;
|
|
}
|
|
p++;
|
|
switch (*p) {
|
|
case 's': {
|
|
char *s=va_arg(args,char *);
|
|
while (*s) {
|
|
sh_sprint_byte(&w,(sh_uint8)*s++);
|
|
}
|
|
break;
|
|
}
|
|
case 'd': {
|
|
double s=va_arg(args,double);
|
|
sh_sprint_double(&w,s);
|
|
break;
|
|
}
|
|
case '1': {
|
|
if (p[1]=='u') {
|
|
sh_sprint_uint8(&w,(sh_uint8)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='s') {
|
|
sh_sprint_int8(&w,(sh_int8)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='U') {
|
|
sh_sprint_uint8_hex(&w,(sh_uint8)va_arg(args,int));
|
|
p++;
|
|
}
|
|
break;
|
|
}
|
|
case '2': {
|
|
if (p[1]=='u') {
|
|
sh_sprint_uint16(&w,(sh_uint16)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='s') {
|
|
sh_sprint_int16(&w,(sh_int16)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='U') {
|
|
sh_sprint_uint16_hex(&w,(sh_uint16)va_arg(args,int));
|
|
p++;
|
|
}
|
|
break;
|
|
}
|
|
case '4': {
|
|
if (p[1]=='u') {
|
|
sh_sprint_uint32(&w,(sh_uint32)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='s') {
|
|
sh_sprint_int32(&w,(sh_int32)va_arg(args,int));
|
|
p++;
|
|
} else if (p[1]=='U') {
|
|
sh_sprint_uint32_hex(&w,(sh_uint32)va_arg(args,int));
|
|
p++;
|
|
}
|
|
break;
|
|
}
|
|
case '8': {
|
|
if (p[1]=='u') {
|
|
sh_sprint_uint64(&w,va_arg(args,unsigned long long));
|
|
p++;
|
|
} else if (p[1]=='s') {
|
|
sh_sprint_int64(&w,va_arg(args,long long));
|
|
p++;
|
|
} else if (p[1]=='U') {
|
|
sh_sprint_uint64_hex(&w,va_arg(args,unsigned long long));
|
|
p++;
|
|
}
|
|
break;
|
|
}
|
|
case 'x': {
|
|
sh_uint64 x=va_arg(args,sh_uint64);
|
|
sh_sprint_uint64_hex_fixed(&w,x);
|
|
break;
|
|
}
|
|
case 'c': {
|
|
sh_sprint_byte(&w,(sh_uint8)va_arg(args,int));
|
|
break;
|
|
}
|
|
case '%': {
|
|
sh_sprint_byte(&w,'%');
|
|
break;
|
|
}
|
|
default:
|
|
sh_sprint_byte(&w,(sh_uint8)*p);
|
|
break;
|
|
}
|
|
}
|
|
va_end(args);
|
|
SH_STATUS status=sh_sprint_byte(&w,'\0');
|
|
if (sh_status_error(status)) {
|
|
output_string[output_len-1]='\0';
|
|
}
|
|
sh_asm_sti();
|
|
return SH_STATUS_SUCCESS;
|
|
}
|