#include "../include/log.h" #include "../include/page.h" sh_uint8 kernel_log_level=0; static inline sh_uint8 inb(sh_uint16 port) { sh_uint8 val; __asm__ volatile ("inb %1, %0":"=a"(val):"Nd"(port)); return val; } static inline void outb(sh_uint16 port,sh_uint8 val) { __asm__ volatile ("outb %0, %1"::"a"(val),"Nd"(port)); } SH_STATUS sh_log_send_byte(sh_uint8 b) { while (!(inb(SH_LOG_SERIAL_PORT_COM1+5) & 0x20)); outb(SH_LOG_SERIAL_PORT_COM1,b); return SH_STATUS_SUCCESS; } SH_STATUS sh_log_send_string(const char* str) { while (*str) { sh_log_send_byte(*str++); } return SH_STATUS_SUCCESS; } SH_STATUS sh_log_send_uintn(sh_uint64 n) { char buf[20]; sh_uint32 i=0; if (n==0) { sh_log_send_byte('0'); return SH_STATUS_SUCCESS; } while (n>0) { buf[i++]='0'+(n%10); n/=10; } while (i--) { sh_log_send_byte(buf[i]); } return SH_STATUS_SUCCESS; } SH_STATUS sh_log_send_uintn_hex(sh_uint64 n) { char buf[16]; sh_uint32 i=0; const char hex_digits[]="0123456789ABCDEF"; if (n==0) { sh_log_send_byte('0'); return SH_STATUS_SUCCESS; } while (n>0) { buf[i++]=hex_digits[n & 0xF]; n>>=4; } while (i--) { sh_log_send_byte(buf[i]); } return SH_STATUS_SUCCESS; } SH_STATUS sh_log_send_double(double value) { if (value<0) { sh_log_send_byte('-'); value=-value; } sh_uint64 integer_part=(sh_uint64)value; double fractional_part=value-(double)integer_part; SH_STATUS status=sh_log_send_uintn(integer_part); if (status!=SH_STATUS_SUCCESS) return status; status=sh_log_send_byte('.'); if (status!=SH_STATUS_SUCCESS) return status; for (int i=0;i<6;i++) { fractional_part*=10.0; sh_uint64 digit=(sh_uint64)fractional_part; status=sh_log_send_byte('0'+(sh_uint8)digit); if (status!=SH_STATUS_SUCCESS) return status; fractional_part-=(double)digit; } return SH_STATUS_SUCCESS; } SH_STATUS sh_log_send_payload(sh_log_OUTPUT_PAYLOAD *payload) { if (payload==SH_NULLPTR) { return SH_STATUS_INVALID_PARAMETER; } if (!(sh_log_output_type_valid(payload->output_type))) { return SH_STATUS_INVALID_PARAMETER; } if (!(sh_log_output_source_valid(payload->output_source))) { return SH_STATUS_INVALID_PARAMETER; } if (payload->output_source!=SH_LOG_SOURCE_TEST && payload->output_typeoutput_source==SH_LOG_SOURCE_MAIN) { sh_log_send_string("Main@"); } else if (payload->output_source==SH_LOG_SOURCE_CONF) { sh_log_send_string("Conf@"); } else if (payload->output_source==SH_LOG_SOURCE_PAGE) { sh_log_send_string("Page@"); } else if (payload->output_source==SH_LOG_SOURCE_SLAB) { sh_log_send_string("Slab@"); } else if (payload->output_source==SH_LOG_SOURCE_TEST) { sh_log_send_string("Test@"); } if (payload->output_type==SH_LOG_DEBUG) { sh_log_send_string("Debug] "); } else if (payload->output_type==SH_LOG_LOG) { sh_log_send_string("Log] "); } else if (payload->output_type==SH_LOG_WARNING) { sh_log_send_string("Warning] "); } else if (payload->output_type==SH_LOG_ERROR) { sh_log_send_string("Error] "); } else if (payload->output_type==SH_LOG_CRITICAL) { sh_log_send_string("Critical] "); } else if (payload->output_type==SH_LOG_FATAL) { sh_log_send_string("Fatal] "); } else if (payload->output_type==SH_LOG_TEST) { sh_log_send_string("Test] "); } sh_log_send_uintn(payload->tsc_value); sh_log_send_string(" : "); sh_log_send_string(payload->message_pointer); return SH_STATUS_SUCCESS; } SH_STATUS sh_log_load_log_level(sh_uint8 log_level) { kernel_log_level=log_level; return SH_STATUS_SUCCESS; } sh_uint8 sh_log_get_log_level() { return kernel_log_level; } SH_STATUS sh_log_test(const char* str) { if (str==SH_NULLPTR) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_TEST, .output_source=SH_LOG_SOURCE_TEST, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } sh_log_send_string("\n"); return SH_STATUS_SUCCESS; } SH_STATUS sh_log_debug(const char* str,sh_log_OUTPUT_SOURCE source) { if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_DEBUG, .output_source=source, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } sh_log_send_string("\n"); return SH_STATUS_SUCCESS; } SH_STATUS sh_log_log(const char* str,sh_log_OUTPUT_SOURCE source) { if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_LOG, .output_source=source, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } sh_log_send_string("\n"); return SH_STATUS_SUCCESS; } SH_STATUS sh_log_warning(const char* str,sh_log_OUTPUT_SOURCE source) { if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_WARNING, .output_source=source, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } sh_log_send_string("\n"); return SH_STATUS_SUCCESS; } SH_STATUS sh_log_error(const char* str,sh_log_OUTPUT_SOURCE source) { if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_ERROR, .output_source=source, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } sh_log_send_string("\n"); return SH_STATUS_SUCCESS; } SH_STATUS sh_log_critical(const char* str,sh_log_OUTPUT_SOURCE source) { if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_CRITICAL, .output_source=source, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } sh_log_send_string("\n"); return SH_STATUS_SUCCESS; } SH_STATUS sh_log_fatal(const char* str,sh_log_OUTPUT_SOURCE source) { if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_FATAL, .output_source=source, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } sh_log_send_string("\n"); return SH_STATUS_SUCCESS; } SH_STATUS sh_log_ltest(const char* str) { if (str==SH_NULLPTR) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_TEST, .output_source=SH_LOG_SOURCE_TEST, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } return SH_STATUS_SUCCESS; } SH_STATUS sh_log_ldebug(const char* str,sh_log_OUTPUT_SOURCE source) { if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_DEBUG, .output_source=source, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } return SH_STATUS_SUCCESS; } SH_STATUS sh_log_llog(const char* str,sh_log_OUTPUT_SOURCE source) { if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_LOG, .output_source=source, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } return SH_STATUS_SUCCESS; } SH_STATUS sh_log_lwarning(const char* str,sh_log_OUTPUT_SOURCE source) { if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_WARNING, .output_source=source, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } return SH_STATUS_SUCCESS; } SH_STATUS sh_log_lerror(const char* str,sh_log_OUTPUT_SOURCE source) { if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_ERROR, .output_source=source, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } return SH_STATUS_SUCCESS; } SH_STATUS sh_log_lcritical(const char* str,sh_log_OUTPUT_SOURCE source) { if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_CRITICAL, .output_source=source, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } return SH_STATUS_SUCCESS; } SH_STATUS sh_log_lfatal(const char* str,sh_log_OUTPUT_SOURCE source) { if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { return SH_STATUS_INVALID_PARAMETER; } sh_log_OUTPUT_PAYLOAD payload={ .output_type=SH_LOG_FATAL, .output_source=source, .tsc_value=sh_tsc_get_kernel_current_tsc(), .message_pointer=str }; SH_STATUS status=sh_log_send_payload(&payload); if (sh_status_error(status)) { return status; } return SH_STATUS_SUCCESS; } SH_STATUS sh_log_mem_stats(sh_log_OUTPUT_SOURCE source) { sh_page_MEM_STATS mem_stats; sh_page_get_memory_stats(&mem_stats); if (sh_log_get_log_level()<=1) { sh_log_llog("Total memory installed (bytes) : ",source); sh_log_send_uintn(mem_stats.memory_total_bytes); sh_log_send_string(" / 0x"); sh_log_send_uintn_hex(mem_stats.memory_total_bytes); sh_log_send_string("\n"); sh_log_llog("Total memory installed (pages) : ",source); sh_log_send_uintn(mem_stats.memory_total_pages); sh_log_send_string(" / 0x"); sh_log_send_uintn_hex(mem_stats.memory_total_pages); sh_log_send_string("\n"); sh_log_llog("Free memory : ",source); sh_log_send_double(mem_stats.free_ratio*100); sh_log_send_string("%\n"); sh_log_llog("Used memory : ",source); sh_log_send_double(mem_stats.used_ratio*100); sh_log_send_string("%\n"); sh_log_llog("Free pages : ",source); sh_log_send_uintn(mem_stats.free_pages); sh_log_send_string("\n"); sh_log_llog("Used pages : ",source); sh_log_send_uintn(mem_stats.used_pages); sh_log_send_string("\n"); sh_log_llog("Largest free block (pages) : ",source); sh_log_send_uintn(mem_stats.largest_free_block); sh_log_send_string("\n"); sh_log_llog("Largest used block (pages) : ",source); sh_log_send_uintn(mem_stats.largest_used_block); sh_log_send_string("\n"); sh_log_llog("Free block count : ",source); sh_log_send_uintn(mem_stats.free_blocks_count); sh_log_send_string("\n"); sh_log_llog("Used block count : ",source); sh_log_send_uintn(mem_stats.used_blocks_count); sh_log_send_string("\n"); sh_log_llog("Total memory taken by physical bitmap (bytes) : ",source); sh_log_send_uintn(mem_stats.physical_bitmap_size_bytes); sh_log_send_string(" / 0x"); sh_log_send_uintn_hex(mem_stats.physical_bitmap_size_bytes); sh_log_send_string("\n"); sh_log_llog("Total memory taken by physical bitmap (pages) : ",source); sh_log_send_uintn(mem_stats.physical_bitmap_size_pages); sh_log_send_string(" / 0x"); sh_log_send_uintn_hex(mem_stats.physical_bitmap_size_pages); sh_log_send_string("\n"); } return SH_STATUS_SUCCESS; }