176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h> 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdint.h> 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdarg.h> 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/io.h> 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <console.h> 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid pause ( void ) { 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "\nPress a key" ); 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman getchar(); 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "\r \r" ); 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid more ( void ) { 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "---more---" ); 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman getchar(); 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "\r \r" ); 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Print row of a hex dump with specified display address 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v dispaddr Display address 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v data Data to print 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v len Length of data 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v offset Starting offset within data 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void dbg_hex_dump_da_row ( unsigned long dispaddr, const void *data, 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned long len, unsigned int offset ) { 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const uint8_t *bytes = data; 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int i; 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t byte; 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "%08lx :", ( dispaddr + offset ) ); 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( i = offset ; i < ( offset + 16 ) ; i++ ) { 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( i >= len ) { 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( " " ); 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman continue; 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "%c%02x", 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ( ( ( i % 16 ) == 8 ) ? '-' : ' ' ), bytes[i] ); 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( " : " ); 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( i = offset ; i < ( offset + 16 ) ; i++ ) { 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( i >= len ) { 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( " " ); 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman continue; 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman byte = bytes[i]; 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ( byte < 0x20 ) || ( byte >= 0x7f ) ) 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman byte = '.'; 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "%c", byte ); 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "\n" ); 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Print hex dump with specified display address 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v dispaddr Display address 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v data Data to print 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v len Length of data 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid dbg_hex_dump_da ( unsigned long dispaddr, const void *data, 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned long len ) { 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int offset; 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( offset = 0 ; offset < len ; offset += 16 ) { 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dbg_hex_dump_da_row ( dispaddr, data, len, offset ); 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define GUARD_SYMBOL ( ( 'M' << 24 ) | ( 'I' << 16 ) | ( 'N' << 8 ) | 'E' ) 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Fill a region with guard markers. We use a 4-byte pattern to make 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * it less likely that check_region will find spurious 1-byte regions 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * of non-corruption. 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid guard_region ( void *region, size_t len ) { 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t offset = 0; 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len &= ~0x03; 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( offset = 0; offset < len ; offset += 4 ) { 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *((uint32_t *)(region + offset)) = GUARD_SYMBOL; 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Check a region that has been guarded with guard_region() for 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * corruption. 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint check_region ( void *region, size_t len ) { 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t corrupted = 0; 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t in_corruption = 0; 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t offset = 0; 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t test = 0; 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len &= ~0x03; 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( offset = 0; offset < len ; offset += 4 ) { 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman test = *((uint32_t *)(region + offset)) = GUARD_SYMBOL; 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ( in_corruption == 0 ) && 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ( test != GUARD_SYMBOL ) ) { 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Start of corruption */ 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( corrupted == 0 ) { 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman corrupted = 1; 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "Region %p-%p (physical %#lx-%#lx) " 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "corrupted\n", 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman region, region + len, 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman virt_to_phys ( region ), 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman virt_to_phys ( region + len ) ); 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman in_corruption = 1; 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "--- offset %#x ", offset ); 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if ( ( in_corruption != 0 ) && 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ( test == GUARD_SYMBOL ) ) { 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* End of corruption */ 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman in_corruption = 0; 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "to offset %#x", offset ); 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( in_corruption != 0 ) { 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "to offset %#zx (end of region)\n", len-1 ); 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return corrupted; 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Maximum number of separately coloured message streams 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Six is the realistic maximum; there are 8 basic ANSI colours, one 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * of which will be the terminal default and one of which will be 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * invisible on the terminal because it matches the background colour. 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define NUM_AUTO_COLOURS 6 13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** A colour assigned to an autocolourised debug message stream */ 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct autocolour { 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /** Message stream ID */ 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned long stream; 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /** Last recorded usage */ 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned long last_used; 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Choose colour index for debug autocolourisation 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v stream Message stream ID 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret colour Colour ID 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int dbg_autocolour ( unsigned long stream ) { 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static struct autocolour acs[NUM_AUTO_COLOURS]; 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static unsigned long use; 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int i; 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int oldest; 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int oldest_last_used; 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Increment usage iteration counter */ 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman use++; 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Scan through list for a currently assigned colour */ 15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) { 16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( acs[i].stream == stream ) { 16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman acs[i].last_used = use; 16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return i; 16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* No colour found; evict the oldest from the list */ 16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman oldest = 0; 16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman oldest_last_used = use; 16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) { 17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( acs[i].last_used < oldest_last_used ) { 17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman oldest_last_used = acs[i].last_used; 17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman oldest = i; 17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman acs[oldest].stream = stream; 17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman acs[oldest].last_used = use; 17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return oldest; 17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Select automatic colour for debug messages 18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v stream Message stream ID 18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid dbg_autocolourise ( unsigned long stream ) { 18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "\033[%dm", 18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ( stream ? ( 31 + dbg_autocolour ( stream ) ) : 0 ) ); 18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Revert to normal colour 19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid dbg_decolourise ( void ) { 19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ( "\033[0m" ); 19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 197