From ca70f03be89a85b745071c1b49b7d82ce7395d8b Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Sat, 10 May 2014 01:06:07 +0200 Subject: [PATCH] Display progress bar during initrd extraction. --- kernel/initrd.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/kernel/initrd.cpp b/kernel/initrd.cpp index 49e55b3c..d1d456ab 100644 --- a/kernel/initrd.cpp +++ b/kernel/initrd.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -60,11 +61,46 @@ struct initrd_context { uint8_t* initrd; size_t initrd_size; + size_t amount_extracted; initrd_superblock_t* sb; Ref links; ioctx_t ioctx; + int last_percent; }; +void initrd_activity(const char* status, const char* format, ...) +{ + Log::PrintF("\r"); + Log::PrintF(" [%6.6s] ", status); + va_list ap; + va_start(ap, format); + Log::PrintFV(format, ap); + va_end(ap); + Log::PrintF("..."); + size_t column, row; + while ( Log::GetCursor(&column, &row), column != Log::Width() ) + Log::PrintF(" "); + Log::PrintF("\e[0J"); +} + +void initrd_activity_done() +{ + Log::PrintF("\r\e[0J"); +} + +void initrd_progress(struct initrd_context* ctx) +{ + int percent = 100; + if ( ctx->initrd_size && ctx->initrd_size != ctx->amount_extracted ) + percent = ((uint64_t) ctx->amount_extracted * 100) / ctx->initrd_size; + if ( percent == ctx->last_percent ) + return; + char status[6 + 1]; + snprintf(status, sizeof(status), " %3i%% ", percent); + initrd_activity(status, "Extracting ramdisk into initial filesystem"); + ctx->last_percent = percent; +} + static mode_t initrd_mode_to_host_mode(uint32_t mode) { mode_t result = mode & 0777; @@ -153,10 +189,15 @@ static bool ExtractFile(struct initrd_context* ctx, initrd_inode_t* inode, Refwrite(&ctx->ioctx, data + sofar, filesize - sofar); + size_t left = filesize - sofar; + size_t chunk = 1024 * 1024; + size_t count = left < chunk ? left : chunk; + ssize_t numbytes = file->write(&ctx->ioctx, data + sofar, count); if ( numbytes <= 0 ) return false; sofar += numbytes; + ctx->amount_extracted += numbytes; + initrd_progress(ctx); } return true; } @@ -220,6 +261,8 @@ static bool ExtractDir(struct initrd_context* ctx, initrd_inode_t* inode, Refamount_extracted += inode->size; + initrd_progress(ctx); return true; } @@ -244,6 +287,8 @@ static bool ExtractNode(struct initrd_context* ctx, initrd_inode_t* inode, Ref desc) { + initrd_activity(" ", "Verifying ramdisk checksum"); + // Allocate the needed kernel virtual address space. addralloc_t initrd_addr_alloc; if ( !AllocateKernelAddress(&initrd_addr_alloc, size) ) @@ -261,6 +306,8 @@ bool ExtractFromPhysicalInto(addr_t physaddr, size_t size, Ref desc) memset(&ctx, 0, sizeof(ctx)); ctx.initrd = (uint8_t*) mapat; ctx.initrd_size = size; + ctx.amount_extracted = 0; + ctx.last_percent = -1; SetupKernelIOCtx(&ctx.ioctx); if ( size < sizeof(*ctx.sb) ) @@ -301,6 +348,10 @@ bool ExtractFromPhysicalInto(addr_t physaddr, size_t size, Ref desc) } } + initrd_activity(" OK ", "Verifying ramdisk checksum"); + + initrd_progress(&ctx); + if ( desc->mkdir(&ctx.ioctx, ".initrd-links", 0777) != 0 ) return false; @@ -342,6 +393,10 @@ bool ExtractFromPhysicalInto(addr_t physaddr, size_t size, Ref desc) // Free the used virtual address space. FreeKernelAddress(&initrd_addr_alloc); + ctx.amount_extracted = ctx.initrd_size; + initrd_progress(&ctx); + initrd_activity_done(); + return true; }