diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml new file mode 100644 index 000000000..d3d5b094a --- /dev/null +++ b/.github/workflows/ccpp.yml @@ -0,0 +1,19 @@ +name: C/C++ CI + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Checkout submodules + uses: textbook/git-checkout-submodule-action@2.0.0 + - name: make + run: cd src && make +# - name: make check +# run: make check +# - name: make distcheck +# run: make distcheck diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..330e39d6d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/libqrencode"] + path = src/libqrencode + url = https://github.com/fukuchi/libqrencode.git diff --git a/src/Makefile b/src/Makefile index 548a4e3f1..3f6cf506f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,7 +4,7 @@ # CLEANUP := -CFLAGS := +CFLAGS := -DHAVE_CONFIG_H ASFLAGS := LDFLAGS := HOST_CFLAGS := @@ -103,6 +103,7 @@ SRCDIRS += hci/mucurses hci/mucurses/widgets SRCDIRS += hci/keymap SRCDIRS += usr SRCDIRS += config +SRCDIRS += libqrencode # These directories contain code that is not eligible for UEFI Secure # Boot signing. @@ -120,6 +121,7 @@ SRCDIRS_INSEC += drivers/net/ath/ath9k NON_AUTO_SRCS := NON_AUTO_SRCS += core/version.c NON_AUTO_SRCS += drivers/net/prism2.c +NON_AUTO_SRCS += libqrencode/qrenc.c # INCDIRS lists the include path # @@ -131,11 +133,11 @@ INCDIRS += include . # Default build target: build the most common targets and print out a # helpfully suggestive message # -ALL := bin/blib.a bin/ipxe.dsk bin/ipxe.lkrn bin/ipxe.iso \ - bin/ipxe.usb bin/ipxe.pxe bin/undionly.kpxe bin/rtl8139.rom \ - bin/8086100e.mrom bin/80861209.rom bin/10500940.rom \ - bin/10222000.rom bin/10ec8139.rom bin/1af41000.rom \ - bin/8086100f.mrom bin/808610d3.mrom bin/15ad07b0.rom +ALL := bin/blib.a bin/ipxe.dsk bin/ipxe.lkrn bin/ipxe.iso \ + bin/ipxe.usb bin/ipxe.pxe bin/undionly.kpxe bin/rtl8139.rom \ + bin/8086100e.mrom bin/80861209.rom bin/10500940.rom \ + bin/10222000.rom bin/10ec8139.rom bin/1af41000.rom \ + bin/8086100f.mrom bin/808610d3.mrom bin/15ad07b0.rom all : $(ALL) @$(ECHO) '===========================================================' diff --git a/src/hci/strerror.c b/src/hci/strerror.c index 1bba8c620..d147ad70b 100644 --- a/src/hci/strerror.c +++ b/src/hci/strerror.c @@ -21,6 +21,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); +int uriqrencode(const char * URI, char *outbuff, size_t outbuff_sz); + /** * Find error description * @@ -76,7 +78,13 @@ static struct errortab * find_closest_error ( int errno ) { * */ char * strerror ( int errno ) { - static char errbuf[64]; + #define SQUARE 46 + + static char errbuf[(((SQUARE/2)+1)*SQUARE)]; +// static char errbuf[64]; + char errURL[32]; + int offset = 0; + struct errortab *errortab; /* Allow for strerror(rc) as well as strerror(errno) */ @@ -86,17 +94,23 @@ char * strerror ( int errno ) { /* Find the error description, if one exists */ errortab = find_closest_error ( errno ); + snprintf ( errURL, sizeof ( errURL ), + PRODUCT_ERROR_URI, + errno ); + /* Construct the error message */ if ( errortab ) { - snprintf ( errbuf, sizeof ( errbuf ), - "%s (" PRODUCT_ERROR_URI ")", - errortab->text, errno ); + offset = snprintf ( &errbuf[offset], sizeof ( errbuf ) - offset, + "%s (%s)", + errortab->text, errURL ); } else { - snprintf ( errbuf, sizeof ( errbuf ), - "Error %#08x (" PRODUCT_ERROR_URI ")", - errno, errno ); + offset = snprintf ( &errbuf[offset], sizeof ( errbuf ) - offset, + "Error %#08x (%s)", + errno, errURL ); } + uriqrencode(errURL, &errbuf[offset], sizeof(errbuf) - offset ); + return errbuf; } diff --git a/src/hci/urlqrencode.c b/src/hci/urlqrencode.c new file mode 100644 index 000000000..a4972bbaf --- /dev/null +++ b/src/hci/urlqrencode.c @@ -0,0 +1,132 @@ +/* Based on code example from libqrencode and modified to use IBM CP 437 chars */ + +#include "libqrencode/qrencode.h" +#include +#include + +#include + +#define margin 4 + +static const char glyphs[] = + " " /* White Space */ + "\xDC" /* Low Block */ + "\xDF" /* High Block */ + "\xDB"; /* Full Block */ + +static int writeANSI_margin(char* outbuff, size_t outbuff_sz, int width, int p_margin, const char *white, const char *reset ) +{ + int y; + int len = 0; + + for (y = 0; y < margin; y+=2 ) { + len += snprintf( &outbuff[len], outbuff_sz - len, "%s", white); /* Initialize the color - default white */ + len += snprintf( &outbuff[len], outbuff_sz - len, "%*c", width + (p_margin*2), ' '); + len += snprintf( &outbuff[len], outbuff_sz - len, "%s\n", reset); // reset to default colors for newline + } + return len; +} + +static int writeANSI(const QRcode *qrcode, char *outbuff, size_t outbuff_sz) +{ + unsigned char *rowH; + unsigned char *rowL; + unsigned char *p; + int x, y; + int len = 0; + + const unsigned char *E = (const unsigned char *)""; + +// const char white[] = "\033[47m"; + const char white[] = ""; + const int white_s = sizeof( white ) -1; +// const char black[] = "\033[40m"; +// const char reset[] = "\033[0m"; + const char reset[] = ""; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuninitialized" + const size_t minLen = (( (white_s) * 2 ) + ( (qrcode->width * 2) * qrcode->width )); // Unlikely +// const size_t maxLen = (( (white_s) * 2 ) + ( (qrcode->width * 2) * qrcode->width * (white_s + 1 ))); // Unlikely +// const size_t typLen = (minLen + maxLen)/2; // More typical? +#pragma GCC diagnostic pop + + if ( outbuff_sz < minLen ) { + snprintf(outbuff, outbuff_sz, "Insufficient buffer to render URL QR-Code.\n\tNeed at least %d bytes, only have %d\n", minLen, outbuff_sz); + // return( -1 ); // Error + } + + /* top margin */ + len += writeANSI_margin(&outbuff[len], outbuff_sz-len, qrcode->width, margin, white, reset); + /* data */ + p = qrcode->data; + for(y = 0; y < qrcode->width; y+=2) { + rowH = (p+((y+0)*qrcode->width)); + rowL = (p+((y+1)*qrcode->width)); + + len += snprintf( &outbuff[len], outbuff_sz - len, "%s", white); /* Initialize the color - default white */ + for(x = 0; x < margin; x++ ){ + len += snprintf( &outbuff[len], outbuff_sz - len, "%s", " "); + } + + for(x = 0; x < qrcode->width; x++) { + len += snprintf( &outbuff[len], outbuff_sz - len, "%c", glyphs[ + ( ((*( rowH+x )&0x1)<<1) | + ((*((y+1)width?rowL+x:E)&0x1)<<0) ) + ]); + } + + for(x = 0; x < margin; x++ ){ + len += snprintf( &outbuff[len], outbuff_sz - len, "%s", " "); + } + len += snprintf( &outbuff[len], outbuff_sz - len, "%s\n", reset); + } + + /* bottom margin */ + len += writeANSI_margin(&outbuff[len], outbuff_sz-len, qrcode->width, margin, white, reset); + + return len; +} + +int uriqrencode(const char * URI, char *outbuff, size_t outbuff_sz) +{ + + QRcode *qrcode = QRcode_encodeString(URI, 0, QR_ECLEVEL_L, + QR_MODE_8, 1); + + outbuff_sz = writeANSI( qrcode, outbuff, outbuff_sz ); + + QRcode_free(qrcode); + return outbuff_sz; +} + +//#define TEST_QRCODE + +#ifdef TEST_QRCODE +int main(int argc, char *argv[]) +{ + #define SQUARE 46 + + char buffer[((SQUARE*2)*SQUARE)]; + char* arg; + + int len; + + if (argc < 2) { + fprintf(stderr, "Usage: %s string\n", argv[0]); + + arg = "https://youtu.be/Xe1o5JDwp2k"; + } else { + arg = argv[1]; + } + + len = uriqrencode( arg, buffer, sizeof( buffer ) ); + + if (len < 0) { + fputs( "Error\n", stdout ); + } + fputs( buffer, stdout ); + + return 0; +} +#endif /* TEST_QRCODE */ diff --git a/src/libqrencode b/src/libqrencode new file mode 160000 index 000000000..13b159f9d --- /dev/null +++ b/src/libqrencode @@ -0,0 +1 @@ +Subproject commit 13b159f9d9509b0c9f5ca0df7a144638337ddb15