Local branch gitlab to github merge
This commit is contained in:
26
.gitignore
vendored
26
.gitignore
vendored
@@ -73,15 +73,41 @@ zputa/*.i
|
||||
zputa/*.ii
|
||||
zputa/*.s
|
||||
zOS/main.save
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
/tzio/
|
||||
.dobuild
|
||||
SD/
|
||||
=======
|
||||
.dobuild
|
||||
SD/
|
||||
common/osd.sav.c
|
||||
>>>>>>> upstream/v2.1-tranZPUter-SW-HW_v2.2
|
||||
=======
|
||||
/tzio/
|
||||
.dobuild
|
||||
SD/
|
||||
>>>>>>> a60e1fd076a2828ee3f5c336a177edcc238197c0
|
||||
frdm/
|
||||
frdmk64f_usb_msd_host_bootloader_mcux.zip
|
||||
frdmk64f_usb_msd_host_bootloader_mcux/
|
||||
getopt_long.c
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
libraries/include/optparse.h
|
||||
minicom.cap
|
||||
startup/app_zos_zpu.tmpl2
|
||||
=======
|
||||
minicom.cap
|
||||
rrrr
|
||||
startup/app_zos_zpu.tmpl2
|
||||
startup/app_zos_zpu.tmpl3
|
||||
tzio/
|
||||
>>>>>>> upstream/v2.1-tranZPUter-SW-HW_v2.2
|
||||
=======
|
||||
libraries/include/optparse.h
|
||||
minicom.cap
|
||||
startup/app_zos_zpu.tmpl2
|
||||
>>>>>>> a60e1fd076a2828ee3f5c336a177edcc238197c0
|
||||
zOS/main.bak
|
||||
|
||||
|
||||
503
apps/tzflupd/tzflupd.c.orig
Normal file
503
apps/tzflupd/tzflupd.c.orig
Normal file
@@ -0,0 +1,503 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: tzdump.c
|
||||
// Created: Jan 2021
|
||||
// Author(s): Philip Smart
|
||||
// Description: A TranZPUter helper utility to update the program in the K64F ARM Processor. This
|
||||
// application takes a binary and flashes it into the K64F Flash Memory in order to
|
||||
// update zOS/ZPUTA or flash any other program (NB. flashing any other program may
|
||||
// need an external OpenSDA programmer to reprogram the K64F with zOS).
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2021 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Jan 2021 - Initial write of the TranZPUter software using NXP/Freescale flash
|
||||
// driver source.
|
||||
// Feb 2021 - Getopt too buggy with long arguments so replaced with optparse.
|
||||
// Mar 2021 - Change sector size to K64F default and fixed some bugs.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// For the Freescale driver code, please see the license at the top of the driver source file.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__K64F__)
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include "k64f_soc.h"
|
||||
#include <../../libraries/include/stdmisc.h>
|
||||
#elif defined(__ZPU__)
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "zpu_soc.h"
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <stdmisc.h>
|
||||
#else
|
||||
#error "Target CPU not defined, use __ZPU__ or __K64F__"
|
||||
#endif
|
||||
#include "interrupts.h"
|
||||
#include "ff.h" /* Declarations of FatFs API */
|
||||
//#include "utils.h"
|
||||
//
|
||||
#if defined __ZPUTA__
|
||||
#include "zputa_app.h"
|
||||
#elif defined __ZOS__
|
||||
#include "zOS_app.h"
|
||||
#else
|
||||
#error OS not defined, use __ZPUTA__ or __ZOS__
|
||||
#endif
|
||||
|
||||
// Getopt_long is buggy so we use optparse.
|
||||
#define OPTPARSE_IMPLEMENTATION
|
||||
#define OPTPARSE_API static
|
||||
#include <optparse.h>
|
||||
|
||||
//
|
||||
#include <app.h>
|
||||
|
||||
#if defined(__K64F__)
|
||||
#include <tranzputer_m.h>
|
||||
#include "tzflupd.h"
|
||||
#include "fsl_flash.h"
|
||||
#endif
|
||||
|
||||
// Utility functions.
|
||||
//#include <tools.c>
|
||||
|
||||
// Version info.
|
||||
#define VERSION "v1.2"
|
||||
#define VERSION_DATE "11/03/2021"
|
||||
#define APP_NAME "TZFLUPD"
|
||||
|
||||
// Global scope variables.
|
||||
FATFS diskHandle;
|
||||
char buffer[FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE];
|
||||
uint8_t FLASH_PROTECTION_SIGNATURE[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf9, 0xff, 0xff};
|
||||
|
||||
// Simple help screen to remmber how this utility works!!
|
||||
//
|
||||
void usage(void)
|
||||
{
|
||||
printf("%s %s\n", APP_NAME, VERSION);
|
||||
printf("\nCommands:-\n");
|
||||
printf(" -h | --help This help text.\n");
|
||||
printf(" -f | --file Binary file to upload and flash into K64F.\n");
|
||||
printf("\nOptions:-\n");
|
||||
printf(" -d | --debug Add debug steps to programming.\n");
|
||||
printf(" -v | --verbose Output more messages.\n");
|
||||
|
||||
printf("\nExamples:\n");
|
||||
printf(" tzflupd -f zOS_22012021_001.bin --verbose # Upload and program the zOS_22012021_001.bin file into the K64F flash memory.\n");
|
||||
}
|
||||
|
||||
// Method to initialise the SD card and mount the first partition. The file we need to upload into the K64F Flash RAM is stored on this card.
|
||||
//
|
||||
FRESULT initSDCard(void)
|
||||
{
|
||||
// Locals.
|
||||
//
|
||||
FRESULT result = FR_NOT_ENABLED;
|
||||
|
||||
// Make a complete initialisation as we are using a new Fat FS instance.
|
||||
//
|
||||
if(!disk_initialize(0, 1))
|
||||
{
|
||||
sprintf(buffer, "0:");
|
||||
result = f_mount(&diskHandle, buffer, 0);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
// Local memory dump routine for debug purposes.
|
||||
//
|
||||
int dumpMemory(uint32_t memaddr, uint32_t memsize, uint32_t memwidth, uint32_t dispaddr, uint8_t dispwidth)
|
||||
{
|
||||
uint8_t displayWidth = dispwidth;;
|
||||
uint32_t pnt = memaddr;
|
||||
uint32_t endAddr = memaddr + memsize;
|
||||
uint32_t addr = dispaddr;
|
||||
uint32_t i = 0;
|
||||
//uint32_t data;
|
||||
int8_t keyIn;
|
||||
char c = 0;
|
||||
|
||||
// If not set, calculate output line width according to connected display width.
|
||||
//
|
||||
if(displayWidth == 0)
|
||||
{
|
||||
switch(getScreenWidth())
|
||||
{
|
||||
case 40:
|
||||
displayWidth = 8;
|
||||
break;
|
||||
case 80:
|
||||
displayWidth = 16;
|
||||
break;
|
||||
default:
|
||||
displayWidth = 32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
printf("%08lX", addr); // print address
|
||||
printf(": ");
|
||||
|
||||
// print hexadecimal data
|
||||
for (i=0; i < displayWidth; )
|
||||
{
|
||||
switch(memwidth)
|
||||
{
|
||||
case 16:
|
||||
if(pnt+i < endAddr)
|
||||
printf("%04X", *(uint16_t *)(pnt+i));
|
||||
else
|
||||
printf(" ");
|
||||
//printf(" ");
|
||||
i+=2;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
if(pnt+i < endAddr)
|
||||
printf("%08lX", *(uint32_t *)(pnt+i));
|
||||
else
|
||||
printf(" ");
|
||||
i+=4;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
default:
|
||||
if(pnt+i < endAddr)
|
||||
printf("%02X", *(uint8_t *)(pnt+i));
|
||||
else
|
||||
printf(" ");
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
fputc((char)' ', stdout);
|
||||
}
|
||||
|
||||
// print ascii data
|
||||
printf(" |");
|
||||
|
||||
// print single ascii char
|
||||
for (i=0; i < displayWidth; i++)
|
||||
{
|
||||
c = (char)*(uint8_t *)(pnt+i);
|
||||
if ((pnt+i < endAddr) && (c >= ' ') && (c <= '~'))
|
||||
fputc((char)c, stdout);
|
||||
else
|
||||
fputc((char)' ', stdout);
|
||||
}
|
||||
|
||||
puts("|");
|
||||
|
||||
// Move on one row.
|
||||
pnt += displayWidth;
|
||||
addr += displayWidth;
|
||||
|
||||
// User abort (ESC), pause (Space) or all done?
|
||||
//
|
||||
keyIn = getKey(0);
|
||||
if(keyIn == ' ')
|
||||
{
|
||||
do {
|
||||
keyIn = getKey(0);
|
||||
} while(keyIn != ' ' && keyIn != 0x1b);
|
||||
}
|
||||
// Escape key pressed, exit with 0 to indicate this to caller.
|
||||
if (keyIn == 0x1b)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
// End of buffer, exit the loop.
|
||||
if(pnt >= (memaddr + memsize))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Normal exit, return -1 to show no key pressed.
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
// Main entry and start point of a zOS/ZPUTA Application. Only 2 parameters are catered for and a 32bit return code, additional parameters can be added by changing the appcrt0.s
|
||||
// startup code to add them to the stack prior to app() call.
|
||||
//
|
||||
// Return code for the ZPU is saved in _memreg by the C compiler, this is transferred to _memreg in zOS/ZPUTA in appcrt0.s prior to return.
|
||||
// The K64F ARM processor uses the standard register passing conventions, return code is stored in R0.
|
||||
//
|
||||
uint32_t app(uint32_t param1, uint32_t param2)
|
||||
{
|
||||
// Initialisation.
|
||||
//
|
||||
int argc = 0;
|
||||
int help_flag = 0;
|
||||
int uploadFNLen = 0;
|
||||
int debug_flag = 0;
|
||||
int verbose_flag = 0;
|
||||
int opt;
|
||||
int updateFNLen = 0;
|
||||
long val = 0;
|
||||
char *argv[20];
|
||||
char *ptr = strtok((char *)param1, " ");
|
||||
char updateFile[32];
|
||||
uint32_t fileSize;
|
||||
uint32_t readSize;
|
||||
uint32_t sizeToRead;
|
||||
uint32_t bytesProcessed;
|
||||
flash_config_t flashDriver; // Flash driver Structure
|
||||
status_t flashResult; // Return code from each flash driver function
|
||||
FRESULT fResult; // Fat FS result.
|
||||
FIL fileHandle; // File Handle.
|
||||
|
||||
// If the invoking command is given, add it to argv at the start.
|
||||
//
|
||||
if(param2 != 0)
|
||||
{
|
||||
argv[argc++] = (char *)param2;
|
||||
}
|
||||
|
||||
// Now convert the parameter line into argc/argv suitable for getopt to use.
|
||||
while (ptr && argc < 20-1)
|
||||
{
|
||||
argv[argc++] = ptr;
|
||||
ptr = strtok(0, " ");
|
||||
}
|
||||
argv[argc] = 0;
|
||||
|
||||
// Define parameters to be processed.
|
||||
struct optparse options;
|
||||
static struct optparse_long long_options[] =
|
||||
{
|
||||
{"help", 'h', OPTPARSE_NONE},
|
||||
{"file", 'f', OPTPARSE_REQUIRED},
|
||||
{"debug", 'd', OPTPARSE_NONE},
|
||||
{"verbose", 'v', OPTPARSE_NONE},
|
||||
{0}
|
||||
};
|
||||
|
||||
// Parse the command line options.
|
||||
//
|
||||
optparse_init(&options, argv);
|
||||
while((opt = optparse_long(&options, long_options, NULL)) != -1)
|
||||
{
|
||||
switch(opt)
|
||||
{
|
||||
case 'h':
|
||||
help_flag = 1;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
strcpy(updateFile, options.optarg);
|
||||
updateFNLen = strlen(updateFile);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
debug_flag = 1;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose_flag = 1;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
printf("%s: %s\n", argv[0], options.errmsg);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the input.
|
||||
if(help_flag == 1)
|
||||
{
|
||||
usage();
|
||||
return(0);
|
||||
}
|
||||
if(updateFNLen == 0)
|
||||
{
|
||||
printf("Update file needs to be specified.\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// As the kernel will be erased we need to assume kernel functionality so initialise kernel features, such as the SD card here as we use them locally.
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
if((fResult=initSDCard()) != FR_OK)
|
||||
{
|
||||
printf("ERROR: Failed to re-initialise the SD card, cannot continue.\n");
|
||||
return(10);
|
||||
}
|
||||
|
||||
// Initialise the flash driver.
|
||||
memset(&flashDriver, 0, sizeof(flash_config_t));
|
||||
flashResult = FLASH_Init(&flashDriver);
|
||||
if (kStatus_FLASH_Success != flashResult)
|
||||
{
|
||||
printf("Error: Failed to initialize Flash memory driver!\n");
|
||||
return(11);
|
||||
}
|
||||
|
||||
// Try and open the source file.
|
||||
fResult = f_open(&fileHandle, updateFile, FA_OPEN_EXISTING | FA_READ);
|
||||
|
||||
// Get the size of the file.
|
||||
if(fResult == FR_OK)
|
||||
fResult = f_lseek(&fileHandle, f_size(&fileHandle));
|
||||
if(fResult == FR_OK)
|
||||
fileSize = (uint32_t)f_tell(&fileHandle);
|
||||
if(fResult == FR_OK)
|
||||
fResult = f_lseek(&fileHandle, 0);
|
||||
|
||||
// Verify that the binary is a K64F program. Do this by comparing the protection area which is static and non changing.
|
||||
//
|
||||
fResult = f_lseek(&fileHandle, FLASH_PROTECTION_START_ADDR);
|
||||
if(fResult == FR_OK)
|
||||
fResult = f_read(&fileHandle, buffer, FLASH_PROTECTION_SIZE, &readSize);
|
||||
if(fResult == FR_OK)
|
||||
{
|
||||
for(int idx=0; idx < FLASH_PROTECTION_SIZE; idx++)
|
||||
{
|
||||
if(buffer[idx] != FLASH_PROTECTION_SIGNATURE[idx])
|
||||
{
|
||||
printf("Error: Update file doesnt look like a valid K64F program binary, aborting!\n");
|
||||
return(12);
|
||||
}
|
||||
}
|
||||
fResult = f_lseek(&fileHandle, 0);
|
||||
}
|
||||
|
||||
// If all ok, indicate file has been opened then prepare to read and flash.
|
||||
if(fResult == FR_OK)
|
||||
{
|
||||
// Indicate file, size and that it has been verified using the security flags.
|
||||
printf("%s %s\n\n", APP_NAME, VERSION);
|
||||
printf("Firmware update file: %s, size=%ld bytes\n\n", updateFile, fileSize);
|
||||
|
||||
printf("*******************************************************************************************************************\n");
|
||||
printf("Flash will now commence, no further output will be made until the flash is successfully programmed.\n");
|
||||
printf("If no further output is seen within 30 seconds, please assume the programming failed and make a hard reset.\n");
|
||||
printf("If device doesnt restart use an OpenSDA or JTAG programmer to reprogram the OS.\n");
|
||||
printf("*******************************************************************************************************************\n");
|
||||
|
||||
// Slight delay to allow the output to flush to the user serial console.
|
||||
uint32_t startTime = *G->millis;
|
||||
while((*G->millis - startTime) < 1000) {};
|
||||
|
||||
// Enter a loop, interrupts disabled, reading sector at a time from the SD card and flashing it into the Flash RAM.
|
||||
//
|
||||
__disable_irq();
|
||||
bytesProcessed = 0;
|
||||
do {
|
||||
sizeToRead = (fileSize-bytesProcessed) > FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE ? FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE : fileSize - bytesProcessed;
|
||||
fResult = f_read(&fileHandle, buffer, sizeToRead, &readSize);
|
||||
if (fResult || readSize == 0) break; /* error or eof */
|
||||
|
||||
// If a sector isnt full, ie. last sector, pad with 0xFF.
|
||||
//
|
||||
if(readSize != FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE)
|
||||
{
|
||||
for(uint16_t idx=readSize; idx < FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE; idx++) { buffer[idx] = 0xFF; }
|
||||
}
|
||||
|
||||
// Flash the sector into the correct location governed by the bytes already processed. We flash a K64F programming sector at a time with unused space set to 0xFF.
|
||||
//
|
||||
flashResult = FLASH_Erase(&flashDriver, bytesProcessed, FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE, kFLASH_ApiEraseKey);
|
||||
// If no previous errors, program the next sector.
|
||||
if(flashResult == kStatus_FLASH_Success)
|
||||
{
|
||||
flashResult = FLASH_Program(&flashDriver, bytesProcessed, (uint32_t*)buffer, FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE);
|
||||
}
|
||||
|
||||
// Update the address/bytes processed count.
|
||||
bytesProcessed += FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE;
|
||||
} while(bytesProcessed < fileSize && flashResult == kStatus_FLASH_Success);
|
||||
__enable_irq();
|
||||
|
||||
// Verbose output.
|
||||
if(verbose_flag)
|
||||
printf("Bytes processed:%ld, exit status:%s\n", bytesProcessed, flashResult == kStatus_FLASH_Success ? "Success" : "Fail");
|
||||
|
||||
// Success in programming, clear rest of flash RAM.
|
||||
if(flashResult == kStatus_FLASH_Success)
|
||||
{
|
||||
// Move to the next full sector as erase operates on sector boundaries.
|
||||
bytesProcessed = bytesProcessed + (bytesProcessed % FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE);
|
||||
|
||||
// Verbose output.
|
||||
if(verbose_flag)
|
||||
printf("Clearing remainder of flash:%ld bytes\n", ((uint32_t)flashDriver.PFlashTotalSize-bytesProcessed));
|
||||
|
||||
// Erase remainder of the device, caters for previous image being larger than update.
|
||||
__disable_irq();
|
||||
flashResult = FLASH_Erase(&flashDriver, bytesProcessed, ((uint32_t)flashDriver.PFlashTotalSize-bytesProcessed), kFLASH_ApiEraseKey);
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
// Any errors, report (assuming kernel still intact) and hang.
|
||||
if (flashResult != kStatus_FLASH_Success)
|
||||
{
|
||||
// This message may not be seen if the kernel has been wiped. put here in-case of error before erase.
|
||||
printf("Error: Failed to program new upgrade into Flash memory area!\n");
|
||||
printf(" Reset device. If device doesnt restart use an OpenSDA or JTAG programmer to reprogram.\n\n");
|
||||
while(1) {};
|
||||
}
|
||||
|
||||
// Debug - place a message in an unused sector which can be checked to see if programming worked.
|
||||
if(debug_flag)
|
||||
{
|
||||
sprintf(buffer, "FLASH PROGRAMMING CHECK MESSAGE");
|
||||
for(uint16_t idx=strlen(buffer); idx < FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE; idx++) { buffer[idx] = 0x00; }
|
||||
__disable_irq();
|
||||
flashResult = FLASH_Erase(&flashDriver, bytesProcessed+FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE, FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE, kFLASH_ApiEraseKey);
|
||||
flashResult = FLASH_Program(&flashDriver, bytesProcessed+FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE, (uint32_t*)buffer, FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE);
|
||||
__enable_irq();
|
||||
printf("Wrote check string at: %08lx\n", bytesProcessed+FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE);
|
||||
}
|
||||
|
||||
// Just in case we have output connectivity. If the update doesnt change too much then we should maintain connectivity with the USB.
|
||||
if(flashResult != kStatus_FLASH_Success)
|
||||
{
|
||||
printf("Error: Flash programming failed, addr:%ld, result:%d\n", bytesProcessed, flashResult);
|
||||
}
|
||||
|
||||
// Tidy up for exit.
|
||||
f_close(&fileHandle);
|
||||
} else
|
||||
{
|
||||
printf("Error: Failed to read update file:%s, aborting!\n", updateFile);
|
||||
return(13);
|
||||
}
|
||||
|
||||
printf("Programming successful, please reset the device to activate update!\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
77
buildall
77
buildall
@@ -4,7 +4,16 @@
|
||||
# TARGET=MZ-700
|
||||
# TARGET=MZ-80A
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
ZPU_SHARPMZ_BUILD=1
|
||||
=======
|
||||
TARGET=MZ-80A
|
||||
ZPU_SHARPMZ_BUILD=0
|
||||
>>>>>>> upstream/v2.1-tranZPUter-SW-HW_v2.2
|
||||
=======
|
||||
ZPU_SHARPMZ_BUILD=1
|
||||
>>>>>>> a60e1fd076a2828ee3f5c336a177edcc238197c0
|
||||
#ZPU_SHARPMZ_APPADDR=0x100000
|
||||
#ZPU_SHARPMZ_APPSIZE=0x70000
|
||||
#ZPU_SHARPMZ_HEAPSIZE=0x8000
|
||||
@@ -59,6 +68,10 @@ if [ "${ZPU_E115_BUILD}x" != "x" -a ${ZPU_E115_BUILD} = 1 ]; then
|
||||
cp -r build/SD/* SD/Dev/
|
||||
fi
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> a60e1fd076a2828ee3f5c336a177edcc238197c0
|
||||
echo "Building for K64F"
|
||||
./build.sh -C K64F -O zos -N 0x10000 -d -T
|
||||
if [ $? != 0 ]; then
|
||||
@@ -86,6 +99,27 @@ cp ${ROOT_DIR}/zSoft/zOS/main.bin ${ROOT_DIR}/zSoft/zOS/main.bak
|
||||
if [ $? != 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
if [ "${TARGET}x" != "x" -a "${TARGET}" = "MZ-80A" ]; then
|
||||
echo "Building for K64F on MZ-80A"
|
||||
./build.sh -C K64F -O zos -N 0x10000 -d -T
|
||||
if [ $? != 0 ]; then
|
||||
echo "Error building K64F Distribution..."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Building for K64F"
|
||||
./build.sh -C K64F -O zos -N 0x18000 -d -T
|
||||
if [ $? != 0 ]; then
|
||||
echo "Error building K64F Distribution..."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
cp -r build/SD/* SD/K64F/
|
||||
>>>>>>> upstream/v2.1-tranZPUter-SW-HW_v2.2
|
||||
=======
|
||||
>>>>>>> a60e1fd076a2828ee3f5c336a177edcc238197c0
|
||||
|
||||
# Ensure the TZFS target directories exist
|
||||
k64fsddir=${ROOT_DIR}/zSoft/SD/K64F
|
||||
@@ -118,6 +152,40 @@ if [ $? != 0 ]; then
|
||||
echo "CPM disks assembly failed..."
|
||||
exit 1
|
||||
fi
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
)
|
||||
if [ $? != 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy the files to the remote build server.
|
||||
cd ${ROOT_DIR}/zSoft
|
||||
rsync -avh * psmart@192.168.15.205:${ROOT_DIR}/zSoft/
|
||||
if [ $? != 0 ]; then
|
||||
echo "Error syncing K64F Distribution..."
|
||||
exit 1
|
||||
fi
|
||||
# Simple mechanism to prevent remote build and programming of the K64F.
|
||||
diff ${ROOT_DIR}/zSoft/zOS/main.bin ${ROOT_DIR}/zSoft/zOS/main.bak
|
||||
if [ $? -ne 0 ]; then
|
||||
cd ${ROOT_DIR}/zSoft
|
||||
echo "GO" > ${ROOT_DIR}/zSoft/.dobuild
|
||||
rsync -avh .dobuild psmart@192.168.15.205:${ROOT_DIR}/zSoft/
|
||||
if [ $? != 0 ]; then
|
||||
echo "Error syncing K64F Distribution..."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
cp ${ROOT_DIR}/zSoft/zOS/main.bin ${ROOT_DIR}/zSoft/zOS/main.bak
|
||||
)
|
||||
if [ $? != 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
>>>>>>> upstream/v2.1-tranZPUter-SW-HW_v2.2
|
||||
=======
|
||||
>>>>>>> a60e1fd076a2828ee3f5c336a177edcc238197c0
|
||||
|
||||
# Use copytosd.sh to transfer files to an SD card. Still need to copy the k64F files manually.
|
||||
# ---------------
|
||||
@@ -136,7 +204,16 @@ fi
|
||||
#cp $tzfsdir/MZF/${TARGET}/* $k64fsddir/MZF/
|
||||
#cp $tzfsdir/BAS/* $k64fsddir/BAS/
|
||||
#cp $tzfsdir/CAS/* $k64fsddir/CAS/
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> a60e1fd076a2828ee3f5c336a177edcc238197c0
|
||||
)
|
||||
if [ $? != 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> upstream/v2.1-tranZPUter-SW-HW_v2.2
|
||||
=======
|
||||
>>>>>>> a60e1fd076a2828ee3f5c336a177edcc238197c0
|
||||
|
||||
403
libraries/include/optparse.h
Normal file
403
libraries/include/optparse.h
Normal file
@@ -0,0 +1,403 @@
|
||||
/* Optparse --- portable, reentrant, embeddable, getopt-like option parser
|
||||
*
|
||||
* This is free and unencumbered software released into the public domain.
|
||||
*
|
||||
* To get the implementation, define OPTPARSE_IMPLEMENTATION.
|
||||
* Optionally define OPTPARSE_API to control the API's visibility
|
||||
* and/or linkage (static, __attribute__, __declspec).
|
||||
*
|
||||
* The POSIX getopt() option parser has three fatal flaws. These flaws
|
||||
* are solved by Optparse.
|
||||
*
|
||||
* 1) Parser state is stored entirely in global variables, some of
|
||||
* which are static and inaccessible. This means only one thread can
|
||||
* use getopt(). It also means it's not possible to recursively parse
|
||||
* nested sub-arguments while in the middle of argument parsing.
|
||||
* Optparse fixes this by storing all state on a local struct.
|
||||
*
|
||||
* 2) The POSIX standard provides no way to properly reset the parser.
|
||||
* This means for portable code that getopt() is only good for one
|
||||
* run, over one argv with one option string. It also means subcommand
|
||||
* options cannot be processed with getopt(). Most implementations
|
||||
* provide a method to reset the parser, but it's not portable.
|
||||
* Optparse provides an optparse_arg() function for stepping over
|
||||
* subcommands and continuing parsing of options with another option
|
||||
* string. The Optparse struct itself can be passed around to
|
||||
* subcommand handlers for additional subcommand option parsing. A
|
||||
* full reset can be achieved by with an additional optparse_init().
|
||||
*
|
||||
* 3) Error messages are printed to stderr. This can be disabled with
|
||||
* opterr, but the messages themselves are still inaccessible.
|
||||
* Optparse solves this by writing an error message in its errmsg
|
||||
* field. The downside to Optparse is that this error message will
|
||||
* always be in English rather than the current locale.
|
||||
*
|
||||
* Optparse should be familiar with anyone accustomed to getopt(), and
|
||||
* it could be a nearly drop-in replacement. The option string is the
|
||||
* same and the fields have the same names as the getopt() global
|
||||
* variables (optarg, optind, optopt).
|
||||
*
|
||||
* Optparse also supports GNU-style long options with optparse_long().
|
||||
* The interface is slightly different and simpler than getopt_long().
|
||||
*
|
||||
* By default, argv is permuted as it is parsed, moving non-option
|
||||
* arguments to the end. This can be disabled by setting the `permute`
|
||||
* field to 0 after initialization.
|
||||
*/
|
||||
#ifndef OPTPARSE_H
|
||||
#define OPTPARSE_H
|
||||
|
||||
#ifndef OPTPARSE_API
|
||||
# define OPTPARSE_API
|
||||
#endif
|
||||
|
||||
struct optparse {
|
||||
char **argv;
|
||||
int permute;
|
||||
int optind;
|
||||
int optopt;
|
||||
char *optarg;
|
||||
char errmsg[64];
|
||||
int subopt;
|
||||
};
|
||||
|
||||
enum optparse_argtype {
|
||||
OPTPARSE_NONE,
|
||||
OPTPARSE_REQUIRED,
|
||||
OPTPARSE_OPTIONAL
|
||||
};
|
||||
|
||||
struct optparse_long {
|
||||
const char *longname;
|
||||
int shortname;
|
||||
enum optparse_argtype argtype;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the parser state.
|
||||
*/
|
||||
OPTPARSE_API
|
||||
void optparse_init(struct optparse *options, char **argv);
|
||||
|
||||
/**
|
||||
* Read the next option in the argv array.
|
||||
* @param optstring a getopt()-formatted option string.
|
||||
* @return the next option character, -1 for done, or '?' for error
|
||||
*
|
||||
* Just like getopt(), a character followed by no colons means no
|
||||
* argument. One colon means the option has a required argument. Two
|
||||
* colons means the option takes an optional argument.
|
||||
*/
|
||||
OPTPARSE_API
|
||||
int optparse(struct optparse *options, const char *optstring);
|
||||
|
||||
/**
|
||||
* Handles GNU-style long options in addition to getopt() options.
|
||||
* This works a lot like GNU's getopt_long(). The last option in
|
||||
* longopts must be all zeros, marking the end of the array. The
|
||||
* longindex argument may be NULL.
|
||||
*/
|
||||
OPTPARSE_API
|
||||
int optparse_long(struct optparse *options,
|
||||
const struct optparse_long *longopts,
|
||||
int *longindex);
|
||||
|
||||
/**
|
||||
* Used for stepping over non-option arguments.
|
||||
* @return the next non-option argument, or NULL for no more arguments
|
||||
*
|
||||
* Argument parsing can continue with optparse() after using this
|
||||
* function. That would be used to parse the options for the
|
||||
* subcommand returned by optparse_arg(). This function allows you to
|
||||
* ignore the value of optind.
|
||||
*/
|
||||
OPTPARSE_API
|
||||
char *optparse_arg(struct optparse *options);
|
||||
|
||||
/* Implementation */
|
||||
#ifdef OPTPARSE_IMPLEMENTATION
|
||||
|
||||
#define OPTPARSE_MSG_INVALID "invalid option"
|
||||
#define OPTPARSE_MSG_MISSING "option requires an argument"
|
||||
#define OPTPARSE_MSG_TOOMANY "option takes no arguments"
|
||||
|
||||
static int
|
||||
optparse_error(struct optparse *options, const char *msg, const char *data)
|
||||
{
|
||||
unsigned p = 0;
|
||||
const char *sep = " -- '";
|
||||
while (*msg)
|
||||
options->errmsg[p++] = *msg++;
|
||||
while (*sep)
|
||||
options->errmsg[p++] = *sep++;
|
||||
while (p < sizeof(options->errmsg) - 2 && *data)
|
||||
options->errmsg[p++] = *data++;
|
||||
options->errmsg[p++] = '\'';
|
||||
options->errmsg[p++] = '\0';
|
||||
return '?';
|
||||
}
|
||||
|
||||
OPTPARSE_API
|
||||
void
|
||||
optparse_init(struct optparse *options, char **argv)
|
||||
{
|
||||
options->argv = argv;
|
||||
options->permute = 1;
|
||||
options->optind = 1;
|
||||
options->subopt = 0;
|
||||
options->optarg = 0;
|
||||
options->errmsg[0] = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
optparse_is_dashdash(const char *arg)
|
||||
{
|
||||
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
optparse_is_shortopt(const char *arg)
|
||||
{
|
||||
return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
optparse_is_longopt(const char *arg)
|
||||
{
|
||||
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0';
|
||||
}
|
||||
|
||||
static void
|
||||
optparse_permute(struct optparse *options, int index)
|
||||
{
|
||||
char *nonoption = options->argv[index];
|
||||
int i;
|
||||
for (i = index; i < options->optind - 1; i++)
|
||||
options->argv[i] = options->argv[i + 1];
|
||||
options->argv[options->optind - 1] = nonoption;
|
||||
}
|
||||
|
||||
static int
|
||||
optparse_argtype(const char *optstring, char c)
|
||||
{
|
||||
int count = OPTPARSE_NONE;
|
||||
if (c == ':')
|
||||
return -1;
|
||||
for (; *optstring && c != *optstring; optstring++);
|
||||
if (!*optstring)
|
||||
return -1;
|
||||
if (optstring[1] == ':')
|
||||
count += optstring[2] == ':' ? 2 : 1;
|
||||
return count;
|
||||
}
|
||||
|
||||
OPTPARSE_API
|
||||
int
|
||||
optparse(struct optparse *options, const char *optstring)
|
||||
{
|
||||
int type;
|
||||
char *next;
|
||||
char *option = options->argv[options->optind];
|
||||
options->errmsg[0] = '\0';
|
||||
options->optopt = 0;
|
||||
options->optarg = 0;
|
||||
if (option == 0) {
|
||||
return -1;
|
||||
} else if (optparse_is_dashdash(option)) {
|
||||
options->optind++; /* consume "--" */
|
||||
return -1;
|
||||
} else if (!optparse_is_shortopt(option)) {
|
||||
if (options->permute) {
|
||||
int index = options->optind++;
|
||||
int r = optparse(options, optstring);
|
||||
optparse_permute(options, index);
|
||||
options->optind--;
|
||||
return r;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
option += options->subopt + 1;
|
||||
options->optopt = option[0];
|
||||
type = optparse_argtype(optstring, option[0]);
|
||||
next = options->argv[options->optind + 1];
|
||||
switch (type) {
|
||||
case -1: {
|
||||
char str[2] = {0, 0};
|
||||
str[0] = option[0];
|
||||
options->optind++;
|
||||
return optparse_error(options, OPTPARSE_MSG_INVALID, str);
|
||||
}
|
||||
case OPTPARSE_NONE:
|
||||
if (option[1]) {
|
||||
options->subopt++;
|
||||
} else {
|
||||
options->subopt = 0;
|
||||
options->optind++;
|
||||
}
|
||||
return option[0];
|
||||
case OPTPARSE_REQUIRED:
|
||||
options->subopt = 0;
|
||||
options->optind++;
|
||||
if (option[1]) {
|
||||
options->optarg = option + 1;
|
||||
} else if (next != 0) {
|
||||
options->optarg = next;
|
||||
options->optind++;
|
||||
} else {
|
||||
char str[2] = {0, 0};
|
||||
str[0] = option[0];
|
||||
options->optarg = 0;
|
||||
return optparse_error(options, OPTPARSE_MSG_MISSING, str);
|
||||
}
|
||||
return option[0];
|
||||
case OPTPARSE_OPTIONAL:
|
||||
options->subopt = 0;
|
||||
options->optind++;
|
||||
if (option[1])
|
||||
options->optarg = option + 1;
|
||||
else
|
||||
options->optarg = 0;
|
||||
return option[0];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPTPARSE_API
|
||||
char *
|
||||
optparse_arg(struct optparse *options)
|
||||
{
|
||||
char *option = options->argv[options->optind];
|
||||
options->subopt = 0;
|
||||
if (option != 0)
|
||||
options->optind++;
|
||||
return option;
|
||||
}
|
||||
|
||||
static int
|
||||
optparse_longopts_end(const struct optparse_long *longopts, int i)
|
||||
{
|
||||
return !longopts[i].longname && !longopts[i].shortname;
|
||||
}
|
||||
|
||||
static void
|
||||
optparse_from_long(const struct optparse_long *longopts, char *optstring)
|
||||
{
|
||||
char *p = optstring;
|
||||
int i;
|
||||
for (i = 0; !optparse_longopts_end(longopts, i); i++) {
|
||||
if (longopts[i].shortname && longopts[i].shortname < 127) {
|
||||
int a;
|
||||
*p++ = longopts[i].shortname;
|
||||
for (a = 0; a < (int)longopts[i].argtype; a++)
|
||||
*p++ = ':';
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
/* Unlike strcmp(), handles options containing "=". */
|
||||
static int
|
||||
optparse_longopts_match(const char *longname, const char *option)
|
||||
{
|
||||
const char *a = option, *n = longname;
|
||||
if (longname == 0)
|
||||
return 0;
|
||||
for (; *a && *n && *a != '='; a++, n++)
|
||||
if (*a != *n)
|
||||
return 0;
|
||||
return *n == '\0' && (*a == '\0' || *a == '=');
|
||||
}
|
||||
|
||||
/* Return the part after "=", or NULL. */
|
||||
static char *
|
||||
optparse_longopts_arg(char *option)
|
||||
{
|
||||
for (; *option && *option != '='; option++);
|
||||
if (*option == '=')
|
||||
return option + 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
optparse_long_fallback(struct optparse *options,
|
||||
const struct optparse_long *longopts,
|
||||
int *longindex)
|
||||
{
|
||||
int result;
|
||||
char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */
|
||||
optparse_from_long(longopts, optstring);
|
||||
result = optparse(options, optstring);
|
||||
if (longindex != 0) {
|
||||
*longindex = -1;
|
||||
if (result != -1) {
|
||||
int i;
|
||||
for (i = 0; !optparse_longopts_end(longopts, i); i++)
|
||||
if (longopts[i].shortname == options->optopt)
|
||||
*longindex = i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
OPTPARSE_API
|
||||
int
|
||||
optparse_long(struct optparse *options,
|
||||
const struct optparse_long *longopts,
|
||||
int *longindex)
|
||||
{
|
||||
int i;
|
||||
char *option = options->argv[options->optind];
|
||||
if (option == 0) {
|
||||
return -1;
|
||||
} else if (optparse_is_dashdash(option)) {
|
||||
options->optind++; /* consume "--" */
|
||||
return -1;
|
||||
} else if (optparse_is_shortopt(option)) {
|
||||
return optparse_long_fallback(options, longopts, longindex);
|
||||
} else if (!optparse_is_longopt(option)) {
|
||||
if (options->permute) {
|
||||
int index = options->optind++;
|
||||
int r = optparse_long(options, longopts, longindex);
|
||||
optparse_permute(options, index);
|
||||
options->optind--;
|
||||
return r;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse as long option. */
|
||||
options->errmsg[0] = '\0';
|
||||
options->optopt = 0;
|
||||
options->optarg = 0;
|
||||
option += 2; /* skip "--" */
|
||||
options->optind++;
|
||||
for (i = 0; !optparse_longopts_end(longopts, i); i++) {
|
||||
const char *name = longopts[i].longname;
|
||||
if (optparse_longopts_match(name, option)) {
|
||||
char *arg;
|
||||
if (longindex)
|
||||
*longindex = i;
|
||||
options->optopt = longopts[i].shortname;
|
||||
arg = optparse_longopts_arg(option);
|
||||
if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) {
|
||||
return optparse_error(options, OPTPARSE_MSG_TOOMANY, name);
|
||||
} if (arg != 0) {
|
||||
options->optarg = arg;
|
||||
} else if (longopts[i].argtype == OPTPARSE_REQUIRED) {
|
||||
options->optarg = options->argv[options->optind];
|
||||
if (options->optarg == 0)
|
||||
return optparse_error(options, OPTPARSE_MSG_MISSING, name);
|
||||
else
|
||||
options->optind++;
|
||||
}
|
||||
return options->optopt;
|
||||
}
|
||||
}
|
||||
return optparse_error(options, OPTPARSE_MSG_INVALID, option);
|
||||
}
|
||||
|
||||
#endif /* OPTPARSE_IMPLEMENTATION */
|
||||
#endif /* OPTPARSE_H */
|
||||
Reference in New Issue
Block a user