diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 9783859..7dd32dd 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -30,7 +30,7 @@ __attribute__((interrupt)) void isr_page_fault(__attribute__((unused)) struct in __asm__ volatile("mov %%cr2, %0" : "=r"(cr2)); char msg[80]; - string_format("EXCEPTION: page fault; addr=%x err=%x", 80, msg, cr2, error_code); + string_format("EXCEPTION: page fault; addr=%lx err=%lx", 80, msg, cr2, error_code); vga_set_string(VGA_HEIGHT - 1, 0, msg, 0x4F); while (1) diff --git a/src/kernel/log.h b/src/kernel/log.h index 506298e..9a7b8d3 100644 --- a/src/kernel/log.h +++ b/src/kernel/log.h @@ -8,7 +8,7 @@ extern stream_t *kernel_log; #define LOG(fmt, ...) \ do { \ - uint64_t _size = string_length(fmt) * 2; \ + uint64_t _size = string_length(fmt) * 10; \ char *_string = memory_allocate(_size); \ _size = string_format(fmt, _size, _string, ##__VA_ARGS__); \ kernel_log->write(kernel_log, _string, _size); \ @@ -17,4 +17,26 @@ extern stream_t *kernel_log; #define TRACE(fmt, ...) +#define LOG_LN(fmt, ...) \ + do { \ + uint64_t _size = string_length(fmt) * 10; \ + char *_string = memory_allocate(_size); \ + _size = string_format(fmt, _size, _string, ##__VA_ARGS__); \ + kernel_log->write(kernel_log, __func__, string_length(__func__)); \ + kernel_log->write(kernel_log, ": ", 2); \ + kernel_log->write(kernel_log, _string, _size); \ + kernel_log->write(kernel_log, "\n", 1); \ + memory_free(_string); \ + } while (0) + +#define LOG_VAL(v) LOG_LN(#v "=%x") + +#define LOG_VAL_F(v, f) LOG_LN(#v "=" f) + +#define TRACE_LN(fmt, ...) + +#define TRACE_VAL(v) TRACE_LN(#v "=%lx") + +#define TRACE_VAL_F(v, f) TRACE_LN(#v "=" f) + void log_init(stream_t *log); diff --git a/src/kernel/memory.c b/src/kernel/memory.c index 16f47ee..e63b1b6 100644 --- a/src/kernel/memory.c +++ b/src/kernel/memory.c @@ -67,10 +67,10 @@ void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags) { const uint64_t pd_index = (ivirt >> 21) & 0x1FF; const uint64_t pt_index = (ivirt >> 12) & 0x1FF; - TRACE("memory_page_map: Mapping physical %x to virtual %x / [%u, %u, %u, %u]...\n", phys, virt, pml4_index, pdpt_index, pd_index, pt_index); + TRACE_LN("Mapping physical %lx to virtual %lx / [%u, %u, %u, %u]...", phys, virt, pml4_index, pdpt_index, pd_index, pt_index); if (!(pml4[pml4_index] & PAGE_PRESENT)) { - TRACE("memory_page_map: PML4 entry %u does not exist, creating...\n", pml4_index); + TRACE_LN("PML4 entry %u does not exist, creating...", pml4_index); uint64_t *pdpt = memory_page_allocate(); memory_set(0, PAGE_SIZE, PHYS_TO_VIRT(pdpt)); pml4[pml4_index] = (uint64_t)pdpt | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; @@ -78,7 +78,7 @@ void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags) { uint64_t *pdpt = PHYS_TO_VIRT(pml4[pml4_index] & ~(uint64_t)0xFFF); if (!(pdpt[pdpt_index] & PAGE_PRESENT)) { - TRACE("memory_page_map: PDPT entry %u does not exist, creating...\n", pdpt_index); + TRACE_LN("PDPT entry %u does not exist, creating...", pdpt_index); uint64_t *pd = memory_page_allocate(); memory_set(0, PAGE_SIZE, PHYS_TO_VIRT(pd)); pdpt[pdpt_index] = (uint64_t)pd | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; @@ -87,7 +87,7 @@ void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags) { uint64_t *pd = PHYS_TO_VIRT(pdpt[pdpt_index] & ~(uint64_t)0xFFF); ASSERT(!(pd[pd_index] & 0x80), "memory_page_map: Huge page in PD."); if (!(pd[pd_index] & PAGE_PRESENT)) { - TRACE("memory_page_map: PD entry %u does not exist, creating...\n", pd_index); + TRACE_LN("PD entry %u does not exist, creating...", pd_index); uint64_t *pt = memory_page_allocate(); memory_set(0, PAGE_SIZE, PHYS_TO_VIRT(pt)); pd[pd_index] = (uint64_t)pt | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; @@ -97,13 +97,11 @@ void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags) { ASSERT(!(pt[pt_index] & PAGE_PRESENT), "memory_page_map: Page already mapped.") - TRACE("memory_page_map: PT entry %u does not exist, creating...\n", pt_index); - + TRACE_LN("PT entry %u does not exist, creating...", pt_index); pt[pt_index] = (uint64_t)phys | flags | PAGE_PRESENT; + TRACE_VAL(pt[pt_index]); - TRACE("memory_page_map: Created %x.\n", pt[pt_index]); - - TRACE("memory_page_map: Done.\n"); + TRACE_LN("Done."); } void memory_page_unmap(uint64_t *pml4, void *virt) { diff --git a/src/kernel/nvme.c b/src/kernel/nvme.c index 5f147ea..0950338 100644 --- a/src/kernel/nvme.c +++ b/src/kernel/nvme.c @@ -5,7 +5,6 @@ #include "src/kernel/pci.h" #include "src/lib/layout.h" #include "src/lib/memory.h" -#include #define SECTOR_SIZE 512 @@ -67,89 +66,83 @@ static uint16_t io_cq_head = 0; static void admin_exec_sync(nvme_sqe_t *cmd) { cmd->cid = admin_sq_tail; - TRACE("admin_exec_sync: Queueing submission...\n"); - TRACE("admin_exec_sync: opc=%x\n", cmd->opc); - TRACE("admin_exec_sync: nsid=%x\n", cmd->nsid); - TRACE("admin_exec_sync: cdw10=%x\n", cmd->cdw10); - TRACE("admin_exec_sync: cdw11=%x\n", cmd->cdw11); - TRACE("admin_exec_sync: cdw12=%x\n", cmd->cdw12); - TRACE("admin_exec_sync: prp1=%x\n", cmd->prp1); - TRACE("admin_exec_sync: prp2=%x\n", cmd->prp2); + TRACE_LN("Queueing submission..."); + TRACE_VAL_F(cmd->opc, "%hhx"); + TRACE_VAL_F(cmd->nsid, "%x"); + TRACE_VAL_F(cmd->cdw10, "%x"); + TRACE_VAL_F(cmd->cdw11, "%x"); + TRACE_VAL_F(cmd->cdw12, "%x"); + TRACE_VAL_F(cmd->prp1, "%lx"); + TRACE_VAL_F(cmd->prp2, "%lx"); memory_copy(cmd, sizeof(nvme_sqe_t), &admin_sq[admin_sq_tail]); - TRACE("admin_exec_sync: Advancing submission doorbell...\n"); - + TRACE_LN("Advancing submission doorbell..."); *(volatile uint32_t *)((uint8_t *)regs + 0x1000) = admin_sq_tail = (admin_sq_tail + 1) % QUEUE_DEPTH; + TRACE_VAL_F(admin_sq_tail, "%u"); - TRACE("admin_exec_sync: Waiting for completion...\n"); - - while ((admin_cq[admin_cq_head].status & 1) != admin_cq_phase) + TRACE_LN("Waiting for completion..."); + nvme_cqe_t *cmp = &admin_cq[admin_cq_head]; + while ((cmp->status & 1) != admin_cq_phase) ; - TRACE("admin_exec_sync: Received completion...\n"); - TRACE("admin_exec_sync: dw0=%x\n", io_cq[io_cq_head].dw0); - TRACE("admin_exec_sync: reserved=%x\n", io_cq[io_cq_head].reserved); - TRACE("admin_exec_sync: sqhd=%x\n", io_cq[io_cq_head].sqhd); - TRACE("admin_exec_sync: sqid=%x\n", io_cq[io_cq_head].sqid); - TRACE("admin_exec_sync: cid=%x\n", io_cq[io_cq_head].cid); - TRACE("admin_exec_sync: status=%x\n", io_cq[io_cq_head].status); - + TRACE_LN("Received completion..."); + TRACE_VAL_F(cmp->dw0, "%x"); + TRACE_VAL_F(cmp->reserved, "%x"); + TRACE_VAL_F(cmp->sqhd, "%hx"); + TRACE_VAL_F(cmp->sqid, "%hx"); + TRACE_VAL_F(cmp->cid, "%hx"); + TRACE_VAL_F(cmp->status, "%hx"); ASSERT((admin_cq[admin_cq_head].status >> 1) == 0, "admin_exec_sync: NVMe command failed."); - TRACE("admin_exec_sync: Advancing completion doorbell...\n"); - + TRACE_LN("Advancing completion doorbell..."); *(volatile uint32_t *)((uint8_t *)regs + 0x1004) = admin_cq_head = (admin_cq_head + 1) % QUEUE_DEPTH; // TODO Get offset from caps. - admin_cq_phase ^= (admin_cq_head == 0); - TRACE("admin_exec_sync: Done.\n"); + TRACE_LN("Done."); } static void io_exec_sync(nvme_sqe_t *cmd) { cmd->cid = io_sq_tail; - TRACE("io_exec_sync: Queueing submission...\n"); - TRACE("io_exec_sync: opc=%x\n", cmd->opc); - TRACE("io_exec_sync: nsid=%x\n", cmd->nsid); - TRACE("io_exec_sync: cdw10=%x\n", cmd->cdw10); - TRACE("io_exec_sync: cdw11=%x\n", cmd->cdw11); - TRACE("io_exec_sync: cdw12=%x\n", cmd->cdw12); - TRACE("io_exec_sync: prp1=%x\n", cmd->prp1); - TRACE("io_exec_sync: prp2=%x\n", cmd->prp2); + TRACE_LN("Queueing submission..."); + TRACE_VAL_F(cmd->opc, "%hhx"); + TRACE_VAL_F(cmd->nsid, "%x"); + TRACE_VAL_F(cmd->cdw10, "%x"); + TRACE_VAL_F(cmd->cdw11, "%x"); + TRACE_VAL_F(cmd->cdw12, "%x"); + TRACE_VAL_F(cmd->prp1, "%x"); + TRACE_VAL_F(cmd->prp2, "%x"); memory_copy(cmd, sizeof(nvme_sqe_t), &io_sq[io_sq_tail]); - TRACE("io_exec_sync: Advancing submission doorbell...\n"); - + TRACE_LN("Advancing submission doorbell..."); *(volatile uint32_t *)((uint8_t *)regs + 0x1008) = io_sq_tail = (io_sq_tail + 1) % QUEUE_DEPTH; // TODO Get offset from caps. - TRACE("io_exec_sync: Waiting for completion...\n"); - - while ((io_cq[io_cq_head].status & 1) != io_cq_phase) + TRACE_LN("Waiting for completion..."); + nvme_cqe_t *cmp = &io_cq[io_cq_head]; + while ((cmp->status & 1) != io_cq_phase) ; - TRACE("io_exec_sync: Received completion...\n"); - TRACE("io_exec_sync: dw0=%x\n", io_cq[io_cq_head].dw0); - TRACE("io_exec_sync: reserved=%x\n", io_cq[io_cq_head].reserved); - TRACE("io_exec_sync: sqhd=%x\n", io_cq[io_cq_head].sqhd); - TRACE("io_exec_sync: sqid=%x\n", io_cq[io_cq_head].sqid); - TRACE("io_exec_sync: cid=%x\n", io_cq[io_cq_head].cid); - TRACE("io_exec_sync: status=%x\n", io_cq[io_cq_head].status); + TRACE_LN("Received completion..."); + TRACE_VAL_F(cmp->dw0, "%x"); + TRACE_VAL_F(cmp->reserved, "%x"); + TRACE_VAL_F(cmp->sqhd, "%hx"); + TRACE_VAL_F(cmp->sqid, "%hx"); + TRACE_VAL_F(cmp->cid, "%hx"); + TRACE_VAL_F(cmp->status, "%hx"); - ASSERT((io_cq[io_cq_head].status >> 1) == 0, "io_exec_sync: NVMe command failed."); - - TRACE("io_exec_sync: Advancing completion doorbell...\n"); + ASSERT((cmp->status >> 1) == 0, "io_exec_sync: NVMe command failed."); + TRACE_LN("Advancing completion doorbell..."); *(volatile uint32_t *)((uint8_t *)regs + 0x100C) = io_cq_head = (io_cq_head + 1) % QUEUE_DEPTH; // TODO Get offset from caps. - io_cq_phase ^= (io_cq_head == 0); - TRACE("io_exec_sync: Done.\n"); + TRACE_LN("Done."); } void nvme_init() { - LOG("nvme_init: Searching for suitable device...\n"); + LOG_LN("Searching for suitable device..."); uint8_t found = 0; for (uint16_t bus = 0; bus < 256 && !found; bus++) { for (uint8_t device = 0; device < 32 && !found; device++) { @@ -169,11 +162,12 @@ void nvme_init() { uint32_t bar1 = pci_read((uint8_t)bus, device, function, 0x14); uint64_t phys = ((uint64_t)bar1 << 32) | bar0; - LOG("nvme_init: Mapping device to memory, phys %x <-> virt %x\n", phys, regs); + LOG_LN("Mapping device to memory, phys %lx <-> virt %lx...", phys, regs); for (uint8_t i = 0; i < 4; i++) { memory_page_map((void *)KERNEL_VIRTUAL_PML4, (void *)((uint8_t *)regs + i * PAGE_SIZE), (void *)((uint8_t *)phys + i * PAGE_SIZE), PAGE_WRITABLE | PAGE_PCD | PAGE_USER); } + found = 1; } } @@ -182,27 +176,29 @@ void nvme_init() { ASSERT(found, "nvme_init: No suitable devices found."); ASSERT(regs->cap & (1ULL << 37), "nvme_init: NVM command set not supported."); - LOG("nvme_init: Disabling device...\n"); - + LOG_LN("Disabling device..."); regs->cc = 0; + TRACE_VAL_F(regs->cc, "%lx"); while (regs->csts & 1) ; + TRACE_VAL_F(regs->cc, "%lx"); - LOG("nvme_init: Configuring device...\n"); + LOG_LN("Configuring device..."); regs->asq = (uint64_t)(VIRT_TO_PHYS(admin_sq)); - TRACE("nvme_init: Setting ASQ, expected=%x, set=%x...\n", (uint64_t)(VIRT_TO_PHYS(admin_sq)), regs->asq); regs->acq = (uint64_t)(VIRT_TO_PHYS(admin_cq)); - TRACE("nvme_init: Setting ACQ, expected=%x, set=%x...\n", (uint64_t)(VIRT_TO_PHYS(admin_cq)), regs->acq); regs->aqa = (QUEUE_DEPTH - 1) << 16 | (QUEUE_DEPTH - 1); - TRACE("nvme_init: Setting AQA, expected=%x, set=%x...\n", (QUEUE_DEPTH - 1) << 16 | (QUEUE_DEPTH - 1), regs->aqa); + TRACE_VAL_F(regs->asq, "%lx"); + TRACE_VAL_F(regs->acq, "%lx"); + TRACE_VAL_F(regs->aqa, "%lx"); + LOG_LN("Enabling device..."); regs->cc = (4 << 20) | (6 << 16) | (0 << 4) | 1; - LOG("nvme_init: Enabling device, expected=%x, set=%x...\n", (4 << 20) | (6 << 16) | (0 << 4) | 1, regs->cc); + TRACE_VAL_F(regs->cc, "%lx"); while (!(regs->csts & 1)) ; + TRACE_VAL_F(regs->cc, "%lx"); - LOG("nvme_init: Creating I/O completion queue...\n"); - + LOG_LN("Creating I/O completion queue..."); nvme_sqe_t create_io_cq = { .opc = 0x05, .prp1 = (uint64_t)VIRT_TO_PHYS(io_cq), @@ -211,8 +207,7 @@ void nvme_init() { }; admin_exec_sync(&create_io_cq); - LOG("nvme_init: Creating I/O submission queue...\n"); - + LOG_LN("Creating I/O submission queue..."); nvme_sqe_t create_io_sq = { .opc = 0x01, .prp1 = (uint64_t)VIRT_TO_PHYS(io_sq), @@ -221,11 +216,11 @@ void nvme_init() { }; admin_exec_sync(&create_io_sq); - LOG("nvme_init: Done.\n"); + LOG_LN("Done."); } void nvme_read_sectors(uint32_t index, uint8_t count, void *to) { - TRACE("nvme_read_sectors: Reading %u sectors at %u...\n", count, index); + TRACE_LN("Reading %u sectors at %u...", count, index); while (count) { uint64_t remainder = PAGE_SIZE - (uint64_t)to % PAGE_SIZE; @@ -249,11 +244,11 @@ void nvme_read_sectors(uint32_t index, uint8_t count, void *to) { to = (void *)((uint8_t *)to + i_count * SECTOR_SIZE); } - TRACE("nvme_read_sectors: Done.\n", count, index); + TRACE_LN("Done."); } void nvme_write_sectors(uint32_t index, uint8_t count, const void *from) { - TRACE("nvme_write_sectors: Reading %u sectors at %u...\n", count, index); + TRACE_LN("Writing %u sectors at %u...", count, index); while (count) { uint64_t remainder = PAGE_SIZE - (uint64_t)from % PAGE_SIZE; @@ -277,5 +272,5 @@ void nvme_write_sectors(uint32_t index, uint8_t count, const void *from) { from = (void *)((uint8_t *)from + i_count * SECTOR_SIZE); } - TRACE("nvme_write_sectors: Done.\n", count, index); + TRACE_LN("Done."); } diff --git a/src/lib/string.c b/src/lib/string.c index a2d57de..224ac90 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -73,7 +73,7 @@ uint64_t string_split(char *string, char separator, uint64_t max, char **result) return count; } -uint64_t string_byte_to_hex(uint8_t value, uint64_t max, char *result) { +uint64_t string_uint8_to_hex(uint8_t value, uint64_t max, char *result) { if (max == 0) { return 0; } @@ -94,7 +94,7 @@ uint64_t string_byte_to_hex(uint8_t value, uint64_t max, char *result) { uint8_t i = 0; while (value) { uint8_t nibble = value & 0xF; - tmp[i++] = nibble < 10 ? '0' + nibble : 'a' + nibble - 10; + tmp[i++] = nibble < 10 ? '0' + nibble : 'A' + nibble - 10; value >>= 4; } @@ -110,6 +110,117 @@ uint64_t string_byte_to_hex(uint8_t value, uint64_t max, char *result) { return i; } +uint64_t string_uint16_to_hex(uint16_t value, uint64_t max, char *result) { + if (max == 0) { + return 0; + } + + if (max == 1) { + result[0] = '\0'; + return 0; + } + + if (max == 2) { + result[0] = '0'; + result[1] = '\0'; + return 1; + } + + char tmp[5] = "0000"; + + uint8_t i = 0; + while (value) { + uint8_t nibble = value & 0xF; + tmp[i++] = nibble < 10 ? '0' + nibble : 'A' + nibble - 10; + value >>= 4; + } + + result[0] = '0'; + result[1] = 'x'; + + i = 2; + while (i < 6 && i < max - 1) { + result[i] = tmp[5 - i]; + i++; + } + result[i] = '\0'; + return i; +} + +uint64_t string_uint32_to_hex(uint32_t value, uint64_t max, char *result) { + if (max == 0) { + return 0; + } + + if (max == 1) { + result[0] = '\0'; + return 0; + } + + if (max == 2) { + result[0] = '0'; + result[1] = '\0'; + return 1; + } + + char tmp[9] = "00000000"; + + uint8_t i = 0; + while (value) { + uint8_t nibble = value & 0xF; + tmp[i++] = nibble < 10 ? '0' + nibble : 'A' + nibble - 10; + value >>= 4; + } + + result[0] = '0'; + result[1] = 'x'; + + i = 2; + while (i < 10 && i < max - 1) { + result[i] = tmp[9 - i]; + i++; + } + result[i] = '\0'; + return i; +} + +uint64_t string_uint64_to_hex(uint64_t value, uint64_t max, char *result) { + if (max == 0) { + return 0; + } + + if (max == 1) { + result[0] = '\0'; + return 0; + } + + if (max == 2) { + result[0] = '0'; + result[1] = '\0'; + return 1; + } + + char tmp[17] = "0000000000000000"; + + uint8_t i = 0; + while (value) { + uint8_t nibble = value & 0xF; + tmp[i++] = nibble < 10 ? '0' + nibble : 'A' + nibble - 10; + value >>= 4; + } + + result[0] = '0'; + result[1] = 'x'; + + i = 2; + while (i < 18 && i < max - 1) { + result[i] = tmp[17 - i]; + i++; + } + result[i] = '\0'; + return i; +} + uint64_t string_uint_to_decimal(uint64_t value, uint64_t max, char *result) { if (max == 0) { return 0; @@ -149,43 +260,6 @@ uint64_t string_int_to_decimal(int64_t value, uint64_t max, char *result) { return 1 + string_uint_to_decimal((uint64_t)(-value), max - 1, result + 1); } -uint64_t string_uint_to_hex(uint64_t value, uint64_t max, char *result) { - if (max == 0) { - return 0; - } - - if (max == 1) { - result[0] = '\0'; - return 0; - } - - if (max == 2) { - result[0] = '0'; - result[1] = '\0'; - return 1; - } - - char tmp[17] = "0000000000000000"; - - uint8_t i = 0; - while (value) { - uint8_t nibble = value & 0xF; - tmp[i++] = nibble < 10 ? '0' + nibble : 'A' + nibble - 10; - value >>= 4; - } - - result[0] = '0'; - result[1] = 'x'; - - i = 2; - while (i < 18 && i < max - 1) { - result[i] = tmp[17 - i]; - i++; - } - result[i] = '\0'; - return i; -} - uint64_t string_format(const char *format, uint64_t max, char *output, ...) { va_list args; va_start(args, output); @@ -198,31 +272,19 @@ uint64_t string_format(const char *format, uint64_t max, char *output, ...) { output[ri++] = format[fi++]; } else { switch (format[fi + 1]) { - case 'c': + case 'c': { output[ri++] = (char)va_arg(args, int); fi += 2; break; - case 'd': + } + case 'd': { string_int_to_decimal(va_arg(args, int64_t), limit - ri, output + ri); while (output[ri]) { ri++; } fi += 2; break; - case 'u': - string_uint_to_decimal(va_arg(args, uint64_t), limit - ri, output + ri); - while (output[ri]) { - ri++; - } - fi += 2; - break; - case 'x': - string_uint_to_hex(va_arg(args, uint64_t), limit - ri, output + ri); - while (output[ri]) { - ri++; - } - fi += 2; - break; + } case 's': { char *s = va_arg(args, char *); while (*s && ri < limit) { @@ -232,16 +294,91 @@ uint64_t string_format(const char *format, uint64_t max, char *output, ...) { fi += 2; break; } + case 'u': { + string_uint_to_decimal(va_arg(args, uint64_t), limit - ri, output + ri); + while (output[ri]) { + ri++; + } + fi += 2; + break; + } + case 'x': { + string_uint32_to_hex(va_arg(args, uint32_t), limit - ri, output + ri); + while (output[ri]) { + ri++; + } + fi += 2; + break; + } case '%': { output[ri++] = '%'; fi += 2; break; } - default: + case 'h': { + switch (format[fi + 2]) { + case 'x': { + string_uint16_to_hex(va_arg(args, uint64_t), limit - ri, output + ri); + while (output[ri]) { + ri++; + } + fi += 3; + break; + } + case 'h': { + switch (format[fi + 3]) { + case 'x': { + string_uint8_to_hex(va_arg(args, uint64_t), limit - ri, output + ri); + while (output[ri]) { + ri++; + } + fi += 4; + break; + } + default: { + output[ri++] = format[fi++]; + output[ri++] = format[fi++]; + output[ri++] = format[fi++]; + output[ri++] = format[fi++]; + break; + } + } + break; + } + default: { + output[ri++] = format[fi++]; + output[ri++] = format[fi++]; + output[ri++] = format[fi++]; + break; + } + } + break; + } + case 'l': { + switch (format[fi + 2]) { + case 'x': { + string_uint64_to_hex(va_arg(args, uint64_t), limit - ri, output + ri); + while (output[ri]) { + ri++; + } + fi += 3; + break; + } + default: { + output[ri++] = format[fi++]; + output[ri++] = format[fi++]; + output[ri++] = format[fi++]; + break; + } + } + break; + } + default: { output[ri++] = format[fi++]; output[ri++] = format[fi++]; break; } + } } } output[ri] = '\0'; diff --git a/src/lib/string.h b/src/lib/string.h index ddd1de4..6078e1b 100644 --- a/src/lib/string.h +++ b/src/lib/string.h @@ -14,12 +14,16 @@ uint64_t string_trim(char *string, char character, char **result); uint64_t string_split(char *string, char separator, uint64_t max, char **result); -uint64_t string_byte_to_hex(uint8_t value, uint64_t max, char *result); +uint64_t string_uint8_to_hex(uint8_t value, uint64_t max, char *result); + +uint64_t string_uint16_to_hex(uint16_t value, uint64_t max, char *result); + +uint64_t string_uint32_to_hex(uint32_t value, uint64_t max, char *result); + +uint64_t string_uint64_to_hex(uint64_t value, uint64_t max, char *result); uint64_t string_uint_to_decimal(uint64_t value, uint64_t max, char *result); uint64_t string_int_to_decimal(int64_t value, uint64_t max, char *result); -uint64_t string_uint_to_hex(uint64_t value, uint64_t max, char *result); - uint64_t string_format(const char *format, uint64_t max, char *output, ...);