diff --git a/posix/include/CPU_Gpio.h b/posix/include/CPU_Gpio.h new file mode 100644 index 00000000..8683d592 --- /dev/null +++ b/posix/include/CPU_Gpio.h @@ -0,0 +1,72 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#ifndef _CPU_GPIO_H_ +#define _CPU_GPIO_H_ + +#include "include/stdafx.h" + +#if defined(BOARD_WSL) + +#define NF_POSIX_GPIO +// multi bank, each have 36 +#define GPIO_MAX_PIN 36 +#define TOTAL_GPIO_PORTS 36 + +#endif // BOARD_WSL + +#if defined(BOARD_PI_ZERO) + +#define NF_POSIX_GPIO +// 1 bank +#define GPIO_MAX_PIN 27 +#define TOTAL_GPIO_PORTS 27 + +#endif // BOARD_PI_ZERO + +#if defined(BOARD_JH7100) + +#define NF_POSIX_GPIO +// TODO: 1 bank? +#define GPIO_MAX_PIN 48 +#define TOTAL_GPIO_PORTS 48 + +#endif // BOARD_JH7100 + + +#if defined(BOARD_PI_PICO) +// 5 gpios seted as gpin in Nuttx +#define __gpio +#define GPIO_MAX_PIN 30 +#define TOTAL_GPIO_PORTS 5 +#endif + +#if defined(BOARD_PI_ZERO) || defined(BOARD_WSL) +#define __gpio +#include + +struct gpiod_chip *_chip; + +// 9 usable gpios +#define GPIO_MAX_PIN 40 +#define TOTAL_GPIO_PORTS 9 + +static gpiod_line* pinLineStored[GPIO_MAX_PIN]; +static GpioPinValue pinLineValue[GPIO_MAX_PIN]; +#endif + +#if defined(__nuttx__) && defined(__gpio) +static int ioctrlFdReference[GPIO_MAX_PIN]; +static GpioPinValue pinLineValue[GPIO_MAX_PIN]; +#endif + + +#if defined(__gpio) +static GpioPinDriveMode pinDirStored[GPIO_MAX_PIN]; +#endif + +#endif //_CPU_GPIO_H_ diff --git a/posix/include/TargetHAL_Spi.h b/posix/include/TargetHAL_Spi.h new file mode 100644 index 00000000..0eeae0c8 --- /dev/null +++ b/posix/include/TargetHAL_Spi.h @@ -0,0 +1,15 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_HAL_SPI_H_ +#define _TARGET_HAL_SPI_H_ 1 + +// # of buses +#define NUM_SPI_BUSES 0 + +// Maximum number of devices per SPI bus +#define MAX_SPI_DEVICES 5 + +#endif //_TARGET_HAL_SPI_H_ diff --git a/posix/include/TargetPAL_BlockStorage.h b/posix/include/TargetPAL_BlockStorage.h new file mode 100644 index 00000000..0771bccc --- /dev/null +++ b/posix/include/TargetPAL_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/posix/include/Target_Windows_Storage.h b/posix/include/Target_Windows_Storage.h new file mode 100644 index 00000000..23999ab3 --- /dev/null +++ b/posix/include/Target_Windows_Storage.h @@ -0,0 +1,9 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_WINDOWS_STORAGE_H_ +#define _TARGET_WINDOWS_STORAGE_H_ 1 + +#endif //_TARGET_WINDOWS_STORAGE_H_ diff --git a/posix/include/TimerManager.h b/posix/include/TimerManager.h new file mode 100644 index 00000000..aa6dd9d3 --- /dev/null +++ b/posix/include/TimerManager.h @@ -0,0 +1,62 @@ +#ifndef TIMERMANAGER_H_ +#define TIMERMANAGER_H_ + +#include +#include +#include +#include +#include + +extern "C" { + void *create_pthread(void *data); +} + +class TimerManager { +public: + TimerManager(); + TimerManager(long usec, void (*callback)(void)); + ~TimerManager(); + void start(); + void stop(); + void addTimer(long usec, void (*callback)(void)); +private: + class Timer + { + public: + Timer(long usec, void (*callback)(void)) : + duration(usec), + callback(callback), + start(0) + { + } + bool operator ==(Timer other) + { + if ((this->callback == other.callback) && (this->duration == other.duration)) { + return true; + } + return false; + } + void operator =(Timer other) + { + duration = other.duration; + callback = other.callback; + start = other.start; + } + suseconds_t duration; + void (*callback)(void); + suseconds_t start; + }; + Timer setUpTimer(long micro_duration, void (*callback)(void)); + friend void *create_pthread(void *data); + void run(); + bool m_bRunning; + bool m_bGo; + bool one_shot; + long m_lMinSleep; + std::list m_cTimers; + pthread_t m_tTimerThread; + pthread_cond_t m_tGoLockCondition; + pthread_mutex_t m_tGoLock; +}; + +#endif diff --git a/posix/include/basetsd.h b/posix/include/basetsd.h new file mode 100644 index 00000000..b014118f --- /dev/null +++ b/posix/include/basetsd.h @@ -0,0 +1,328 @@ +/* + * Compilers that uses ILP32, LP64 or P64 type models + * for both Win32 and Win64 are supported by this file. + * + * Copyright (C) 1999 Patrik Stridvall + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_BASETSD_H +#define __WINE_BASETSD_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/* + * Win32 was easy to implement under Unix since most 32-bit Unices use the same + * type model (ILP32) as Win32, where int, long and pointer are 32-bit. + * + * Win64, however, can cause some problems. Most 64-bit Unices use the LP64 type + * model where int is 32-bit and long and pointer are 64-bit. Win64 on the other + * hand uses the LLP64 type model where int and long are 32 bit and pointer is + * 64-bit. + */ + +#if (defined(__x86_64__) || defined(__powerpc64__) || defined(__sparc64__) || defined(__aarch64__)) && !defined(_WIN64) +#define _WIN64 +#endif + +/* Type model independent typedefs */ +/* The __intXX types are native types defined by the MS C compiler. + * Apps that make use of them before they get defined here, can + * simply add to the command line: + * -D__int8=char -D__int16=short -D__int32=int "-D__int64=long long" + */ +#if !defined(_MSC_VER) && !defined(__WIDL__) +# ifndef __int8 +# define __int8 char +# endif +# ifndef __int16 +# define __int16 short +# endif +# ifndef __int32 +# define __int32 int +# endif +# ifndef __int64 +# if defined(_WIN64) && !defined(__MINGW64__) +# define __int64 long +# else +# define __int64 long long +# endif +# endif +#endif /* !defined(_MSC_VER) */ + +/* FIXME: DECLSPEC_ALIGN should be declared only in winnt.h, but we need it here too */ +#ifndef DECLSPEC_ALIGN +# if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(MIDL_PASS) +# define DECLSPEC_ALIGN(x) __declspec(align(x)) +# elif defined(__GNUC__) +# define DECLSPEC_ALIGN(x) __attribute__((aligned(x))) +# else +# define DECLSPEC_ALIGN(x) +# endif +#endif + +typedef signed char INT8, *PINT8; +typedef signed short INT16, *PINT16; +typedef signed int INT32, *PINT32; +typedef unsigned char UINT8, *PUINT8; +typedef unsigned short UINT16, *PUINT16; +typedef unsigned int UINT32, *PUINT32; +typedef signed int LONG32, *PLONG32; +typedef unsigned int ULONG32, *PULONG32; +typedef unsigned int DWORD32, *PDWORD32; + +#ifdef _MSC_VER +typedef signed __int64 INT64, *PINT64; +typedef unsigned __int64 UINT64, *PUINT64; +typedef signed __int64 LONG64, *PLONG64; +typedef unsigned __int64 ULONG64, *PULONG64; +typedef unsigned __int64 DWORD64, *PDWORD64; +#else +typedef signed __int64 DECLSPEC_ALIGN(8) INT64, *PINT64; +typedef unsigned __int64 DECLSPEC_ALIGN(8) UINT64, *PUINT64; +typedef signed __int64 DECLSPEC_ALIGN(8) LONG64, *PLONG64; +typedef unsigned __int64 DECLSPEC_ALIGN(8) ULONG64, *PULONG64; +typedef unsigned __int64 DECLSPEC_ALIGN(8) DWORD64, *PDWORD64; +#endif + +/* Basic pointer-sized integer types */ + +#if defined(__midl) || defined(__WIDL__) + +typedef /* [public] */ signed __int3264 INT_PTR, *PINT_PTR; +typedef /* [public] */ signed __int3264 LONG_PTR, *PLONG_PTR; +typedef /* [public] */ unsigned __int3264 UINT_PTR, *PUINT_PTR; +typedef /* [public] */ unsigned __int3264 ULONG_PTR, *PULONG_PTR; +typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; + +#elif defined(_WIN64) + +#define __int3264 __int64 + +typedef signed __int64 INT_PTR, *PINT_PTR; +typedef signed __int64 LONG_PTR, *PLONG_PTR; +typedef unsigned __int64 UINT_PTR, *PUINT_PTR; +typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; +typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; + +#else + +#define __int3264 __int32 + +typedef long INT_PTR, *PINT_PTR; +typedef unsigned long UINT_PTR, *PUINT_PTR; +typedef long LONG_PTR, *PLONG_PTR; +typedef unsigned long ULONG_PTR, *PULONG_PTR; +typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; + +#endif + +/* Win32 or Win64 dependent typedef/defines. */ + +#ifdef _WIN64 + +#define MAXINT_PTR 0x7fffffffffffffff +#define MININT_PTR 0x8000000000000000 +#define MAXUINT_PTR 0xffffffffffffffff + +typedef __int64 SHANDLE_PTR; +typedef unsigned __int64 HANDLE_PTR; +typedef int HALF_PTR, *PHALF_PTR; +typedef unsigned int UHALF_PTR, *PUHALF_PTR; + +#define MAXHALF_PTR 0x7fffffff +#define MINHALF_PTR 0x80000000 +#define MAXUHALF_PTR 0xffffffff + +#if !defined(__midl) && !defined(__WIDL__) + +static inline ULONG32 HandleToULong(const void *h) +{ + return (ULONG32)(ULONG_PTR)h; +} + +static inline LONG32 HandleToLong(const void *h) +{ + return (LONG32)(LONG_PTR)h; +} + +static inline void *ULongToHandle(ULONG32 ul) +{ + return (void *)(ULONG_PTR)ul; +} + +static inline void *LongToHandle(LONG32 l) +{ + return (void *)(LONG_PTR)l; +} + +static inline ULONG32 PtrToUlong(const void *p) +{ + return (ULONG32)(ULONG_PTR)p; +} + +static inline LONG32 PtrToLong(const void *p) +{ + return (LONG32)(LONG_PTR)p; +} + +static inline UINT32 PtrToUint(const void *p) +{ + return (UINT32)(UINT_PTR)p; +} + +static inline INT32 PtrToInt(const void *p) +{ + return (INT32)(INT_PTR)p; +} + +static inline UINT16 PtrToUshort(const void *p) +{ + return (UINT16)(ULONG_PTR)p; +} + +static inline INT16 PtrToShort(const void *p) +{ + return (INT16)(LONG_PTR)p; +} + +static inline void *IntToPtr(INT32 i) +{ + return (void *)(INT_PTR)i; +} + +static inline void *UIntToPtr(UINT32 ui) +{ + return (void *)(UINT_PTR)ui; +} + +static inline void *LongToPtr(LONG32 l) +{ + return (void *)(LONG_PTR)l; +} + +static inline void *ULongToPtr(ULONG32 ul) +{ + return (void *)(ULONG_PTR)ul; +} + +#endif /* !__midl && !__WIDL__ */ + +#else /* FIXME: defined(_WIN32) */ + +#define MAXINT_PTR 0x7fffffff +#define MININT_PTR 0x80000000 +#define MAXUINT_PTR 0xffffffff + +typedef long SHANDLE_PTR; +typedef unsigned long HANDLE_PTR; +typedef signed short HALF_PTR, *PHALF_PTR; +typedef unsigned short UHALF_PTR, *PUHALF_PTR; + +#define MAXUHALF_PTR 0xffff +#define MAXHALF_PTR 0x7fff +#define MINHALF_PTR 0x8000 + +#define HandleToULong(h) ((ULONG)(ULONG_PTR)(h)) +#define HandleToLong(h) ((LONG)(LONG_PTR)(h)) +#define ULongToHandle(ul) ((HANDLE)(ULONG_PTR)(ul)) +#define LongToHandle(l) ((HANDLE)(LONG_PTR)(l)) +#define PtrToUlong(p) ((ULONG)(ULONG_PTR)(p)) +#define PtrToLong(p) ((LONG)(LONG_PTR)(p)) +#define PtrToUint(p) ((UINT)(UINT_PTR)(p)) +#define PtrToInt(p) ((INT)(INT_PTR)(p)) +#define PtrToUshort(p) ((USHORT)(ULONG_PTR)(p)) +#define PtrToShort(p) ((SHORT)(LONG_PTR)(p)) +#define IntToPtr(i) ((void *)(INT_PTR)((INT)i)) +#define UIntToPtr(ui) ((void *)(UINT_PTR)((UINT)ui)) +#define LongToPtr(l) ((void *)(LONG_PTR)((LONG)l)) +#define ULongToPtr(ul) ((void *)(ULONG_PTR)((ULONG)ul)) + +#endif /* defined(_WIN64) || defined(_WIN32) */ + +#define HandleToUlong(h) HandleToULong(h) +#define UlongToHandle(ul) ULongToHandle(ul) +#define UintToPtr(ui) UIntToPtr(ui) +#define UlongToPtr(ul) ULongToPtr(ul) + +typedef LONG_PTR SSIZE_T, *PSSIZE_T; +typedef ULONG_PTR SIZE_T, *PSIZE_T; + +typedef ULONG_PTR KAFFINITY, *PKAFFINITY; + +/* Some Wine-specific definitions */ + +/* Architecture dependent settings. */ +/* These are hardcoded to avoid dependencies on config.h in Winelib apps. */ +#if defined(__i386__) +# undef WORDS_BIGENDIAN +# undef BITFIELDS_BIGENDIAN +# define ALLOW_UNALIGNED_ACCESS +#elif defined(__x86_64__) +# undef WORDS_BIGENDIAN +# undef BITFIELDS_BIGENDIAN +# define ALLOW_UNALIGNED_ACCESS +#elif defined(__sparc__) +# define WORDS_BIGENDIAN +# define BITFIELDS_BIGENDIAN +# undef ALLOW_UNALIGNED_ACCESS +#elif defined(__powerpc__) +# define WORDS_BIGENDIAN +# define BITFIELDS_BIGENDIAN +# undef ALLOW_UNALIGNED_ACCESS +#elif defined(__ALPHA__) +# undef WORDS_BIGENDIAN +# undef BITFIELDS_BIGENDIAN +# undef ALLOW_UNALIGNED_ACCESS +#elif defined(__ARMEB__) +# define WORDS_BIGENDIAN +# define BITFIELDS_BIGENDIAN +# undef ALLOW_UNALIGNED_ACCESS +#elif defined(__ARMEL__) || defined(__arm__) +# undef WORDS_BIGENDIAN +# undef BITFIELDS_BIGENDIAN +# undef ALLOW_UNALIGNED_ACCESS +#elif defined(__AARCH64EB__) +# define WORDS_BIGENDIAN +# define BITFIELDS_BIGENDIAN +# undef ALLOW_UNALIGNED_ACCESS +#elif defined(__AARCH64EL__) || defined(__aarch64__) +# undef WORDS_BIGENDIAN +# undef BITFIELDS_BIGENDIAN +# undef ALLOW_UNALIGNED_ACCESS +#elif defined(__riscv) +# undef WORDS_BIGENDIAN +# undef BITFIELDS_BIGENDIAN +# undef ALLOW_UNALIGNED_ACCESS +#elif defined(__MIPSEB__) +# define WORDS_BIGENDIAN +# define BITFIELDS_BIGENDIAN +# undef ALLOW_UNALIGNED_ACCESS +#elif defined(__MIPSEL__) +# undef WORDS_BIGENDIAN +# undef BITFIELDS_BIGENDIAN +# undef ALLOW_UNALIGNED_ACCESS +#elif !defined(RC_INVOKED) && !defined(__WIDL__) && !defined(__midl) +# error Unknown CPU architecture! +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* !defined(__WINE_BASETSD_H) */ diff --git a/posix/include/include/stdafx.h b/posix/include/include/stdafx.h new file mode 100644 index 00000000..c1426aa8 --- /dev/null +++ b/posix/include/include/stdafx.h @@ -0,0 +1,37 @@ +// TODO: port to linux + +#pragma once + +#if defined(__linux__) || defined(__nuttx__) +#define __cdecl __attribute__((__cdecl__)) +#endif + +typedef const char * LPCSTR; + +#include +//#include + +#define _CRTIMP + +//#define _strninc(_pc,_sz) (((_pc)+(_sz))) +// _CRTIMP size_t __cdecl __strncnt(const char *_Str,size_t _Cnt); + +#include + +// TODO: reference additional headers your program requires here + +#include +#include +#include +#include +#include + +#include "targetHAL.h" +#include "nanoCLR_ParseOptions.h" +#include "basetsd.h" +#include "utils.h" + +// LINUX +#include +#include +#include diff --git a/posix/include/platform_selector.h b/posix/include/platform_selector.h new file mode 100644 index 00000000..e0c42002 --- /dev/null +++ b/posix/include/platform_selector.h @@ -0,0 +1,71 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +// TODO: port to linux + +#ifndef _PLATFORM_WINDOWS_SELECTOR_H_ +#define _PLATFORM_WINDOWS_SELECTOR_H_ 1 + +#define PLATFORM_WINDOWS_EMULATOR 1 + +///////////////////////////////////////////////////////// +// +// macros +// + +#define FAT_FS__VALIDATE_READONLY_CACHELINE 1 +//#define FAT_FS__DO_NOT_UPDATE_FILE_ACCESS_TIME 1 +#define FAT_FS__CACHE_FLUSH_TIMEOUT_USEC (5 * 1000 * 1000) + +// +// macros +// +///////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////// +// +// constants +// +#define PRODUCT_WATCH 1 +#define PRODUCT_AUXDISPLAY 1 + +// Port definitions +#define TOTAL_USART_PORT 2 +#define COM1 ConvertCOM_ComHandle(0) +#define COM2 ConvertCOM_ComHandle(1) + +#define TOTAL_USB_CONTROLLER 1 +#define USB1 ConvertCOM_UsbHandle(0) + +#define TOTAL_DEBUG_PORT 1 +#define COM_DEBUG ConvertCOM_DebugHandle(0) + +#define TOTAL_MESSAGING_PORT 1 +#define COM_MESSAGING ConvertCOM_MessagingHandle(0) + +#define DEBUG_TEXT_PORT COM_DEBUG +#define DEBUGGER_PORT COM_DEBUG +#define MESSAGING_PORT COM_DEBUG + +#define PLATFORM_DEPENDENT_TX_USART_BUFFER_SIZE 512 // there is one TX for each usart port +#define PLATFORM_DEPENDENT_RX_USART_BUFFER_SIZE 512 // there is one RX for each usart port +#define PLATFORM_DEPENDENT_USB_QUEUE_PACKET_COUNT \ + 2 // there is one queue for each pipe of each endpoint and the size of a single packet is sizeof(USB_PACKET64) == 68 + // bytes + +// These are configuration for FATFS, uncomment if non-default values are needed +//#define PLATFORM_DEPENDENT_FATFS_SECTORCACHE_MAXSIZE 8 +//#define PLATFORM_DEPENDENT_FATFS_SECTORCACHE_LINESIZE 2048 +//#define PLATFORM_DEPENDENT_FATFS_MAX_OPEN_HANDLES 8 +#define PLATFORM_DEPENDENT_FATFS_MAX_VOLUMES 8 +// +// constants +// +///////////////////////////////////////////////////////// + +//#include + +#endif // _PLATFORM_WINDOWS_SELECTOR_H_ 1 diff --git a/posix/include/sys_dev_gpio_native_target.h b/posix/include/sys_dev_gpio_native_target.h new file mode 100644 index 00000000..082d66e4 --- /dev/null +++ b/posix/include/sys_dev_gpio_native_target.h @@ -0,0 +1,11 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#ifndef _SYS_DEV_GPIO_NATIVE_TARGET_H_ +#define _SYS_DEV_GPIO_NATIVE_TARGET_H_ + +#endif //_SYS_DEV_GPIO_NATIVE_TARGET_H_ diff --git a/posix/include/targetHAL.h b/posix/include/targetHAL.h new file mode 100644 index 00000000..df4721bb --- /dev/null +++ b/posix/include/targetHAL.h @@ -0,0 +1,97 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_HAL_H_ +#define _TARGET_HAL_H_ + +#include "basetsd.h" + +#if defined(__linux__) || defined(__nuttx__) +#define __cdecl __attribute__((__cdecl__)) +#endif + +// #include + +// set min possible number of sockets +#define PLATFORM_DEPENDENT__SOCKETS_MAX_COUNT 1 + +#if defined(__linux__) || defined(__nuttx__) +#define NANOCLR_STOP() {\ + printf("NANOCLR_STOP");\ + exit(-24);\ +} +#endif + +#if !defined(BUILD_RTM) + +inline void __cdecl HARD_Breakpoint() +{ + // TODO: port to linux + // if (::IsDebuggerPresent()) + // { + // ::DebugBreak(); + // } +} + +#define HARD_BREAKPOINT() HARD_Breakpoint() + +inline bool Target_ConfigUpdateRequiresErase() +{ + return true; +} + +#endif // !defined(BUILD_RTM) + +inline bool Target_HasNanoBooter() +{ + return false; +}; + +inline bool Target_IFUCapable() +{ + return false; +}; + +inline bool Target_HasProprietaryBooter() +{ + return false; +}; + +inline uint32_t GetPlatformCapabilities() +{ + return 0; +}; + +inline uint32_t GetTargetCapabilities() +{ + return 0; +}; + +inline bool RequestToLaunchProprietaryBootloader() +{ + return false; +}; + +inline bool RequestToLaunchNanoBooter() +{ + return false; +}; + +inline uint32_t CPU_TicksPerSecond() +{ + return 100000000; +} + +inline uint64_t CPU_MicrosecondsToTicks(UINT64 uSec) +{ + return uSec * 10; +} + +inline uint64_t CPU_MillisecondsToTicks(UINT64 uSec) +{ + return uSec * 10 * 1000; +} + +#endif //_TARGET_HAL_H_ diff --git a/posix/include/targetHAL_Time.h b/posix/include/targetHAL_Time.h new file mode 100644 index 00000000..b6b9b9d3 --- /dev/null +++ b/posix/include/targetHAL_Time.h @@ -0,0 +1,14 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TARGET_HAL_TIME_H_ +#define _TARGET_HAL_TIME_H_ 1 + +#include + +#define HAL_Time_CurrentSysTicks HAL_Time_CurrentSysTicks +uint64_t HAL_Time_CurrentSysTicks(); + +#endif //_TARGET_HAL_TIME_H_ diff --git a/posix/include/targetPAL.h b/posix/include/targetPAL.h new file mode 100644 index 00000000..c38d2946 --- /dev/null +++ b/posix/include/targetPAL.h @@ -0,0 +1,9 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_PAL_H_ +#define _TARGET_PAL_H_ + +#endif //_TARGET_PAL_H_ diff --git a/posix/include/targetPAL_Time.h b/posix/include/targetPAL_Time.h new file mode 100644 index 00000000..77377877 --- /dev/null +++ b/posix/include/targetPAL_Time.h @@ -0,0 +1,9 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_PAL_TIME_H_ +#define _TARGET_PAL_TIME_H_ 1 + +#endif //_TARGET_PAL_TIME_H_ diff --git a/posix/include/target_BlockStorage.h b/posix/include/target_BlockStorage.h new file mode 100644 index 00000000..0771bccc --- /dev/null +++ b/posix/include/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/posix/include/target_board.h b/posix/include/target_board.h new file mode 100644 index 00000000..2cef17a0 --- /dev/null +++ b/posix/include/target_board.h @@ -0,0 +1,9 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_BOARD_H_ +#define _TARGET_BOARD_H_ + +#endif // _TARGET_BOARD_H_ diff --git a/posix/include/target_common.h b/posix/include/target_common.h new file mode 100644 index 00000000..354271d2 --- /dev/null +++ b/posix/include/target_common.h @@ -0,0 +1,13 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ 1 + +// check Monitor_Ping_Source_Flags enum +#define WP_PACKET_SIZE 256U +////////////////////////////////////////////// + +#endif // _TARGET_COMMON_H_ diff --git a/posix/include/target_os.h b/posix/include/target_os.h new file mode 100644 index 00000000..eaa6dcfa --- /dev/null +++ b/posix/include/target_os.h @@ -0,0 +1,11 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_OS_H_ +#define _TARGET_OS_H_ 1 + +#define TARGET_HAS_NANOBOOTER FALSE + +#endif // _TARGET_OS_H_ diff --git a/posix/include/target_platform.h b/posix/include/target_platform.h new file mode 100644 index 00000000..1f950bda --- /dev/null +++ b/posix/include/target_platform.h @@ -0,0 +1,9 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_PLATFORM_H_ +#define _TARGET_PLATFORM_H_ + +#endif /* _TARGET_PLATFORM_H_ */ diff --git a/posix/include/utils.h b/posix/include/utils.h new file mode 100644 index 00000000..cc1275ce --- /dev/null +++ b/posix/include/utils.h @@ -0,0 +1,32 @@ + +#ifndef _UTILS_H_ +#define _UTILS_H_ 1 + +#include +#include +#include + +#include +#include + +typedef uint8_t BYTE; +typedef uint32_t DWORD; +typedef int32_t LONG; +typedef int64_t LONGLONG; + +typedef union _LARGE_INTEGER { + struct { + DWORD LowPart; + LONG HighPart; + }; + struct { + DWORD LowPart; + LONG HighPart; + } u; + LONGLONG QuadPart; +} LARGE_INTEGER, *PLARGE_INTEGER; + +extern char * utils_charo_char(const char * wchar, size_t len); +extern void print_trace(void); + +#endif //_UTILS_H_ diff --git a/posix/main.cpp b/posix/main.cpp new file mode 100644 index 00000000..16ad138d --- /dev/null +++ b/posix/main.cpp @@ -0,0 +1,120 @@ +#if defined(__nuttx__) +#include +#endif + +#include "include/stdafx.h" +#include +#include +#include +#include + +#define NF_CLR_FEATURE_ALL + +///////////////////////////////////////////////////////////////////////////// + +// All solutions are expected to provide an implementation of this +bool Target_GetReleaseInfo(NFReleaseInfo &releaseInfo) +{ + NFReleaseInfo::Init( + releaseInfo, + VERSION_MAJOR, + VERSION_MINOR, + VERSION_BUILD, + VERSION_REVISION, + OEMSYSTEMINFOSTRING, + hal_strlen_s(OEMSYSTEMINFOSTRING), + TARGETNAMESTRING, + hal_strlen_s(TARGETNAMESTRING), + PLATFORMNAMESTRING, + hal_strlen_s(PLATFORMNAMESTRING)); + + return true; // alternatively, return false if you didn't initialize the releaseInfo structure. +} + +#if defined(__nuttx__) +extern "C" +{ +#endif + +int main(int argc, char *argv[]) +{ + int i = 0; + DIR *d; + struct dirent *dir; + std::vector args; + std::string path; + + if (argc == 2) { + // check for the directory for assemblies to use + path = std::string(argv[1]); + } else { +#if defined(__nuttx__) && !defined(CONFIG_EXAMPLES_NF_ROMFS) + // simple ignore and use default sdcard + path = std::string("/mnt/sd0/"); +#elif defined(__nuttx__) && defined(CONFIG_EXAMPLES_NF_ROMFS) + path = std::string("/nf/"); +#else + // simple ignore and use current dir + path = std::string("./"); +#endif + } + +#if defined(DEBUG) + printf(".NET nanoFramework nanoCLR Nuttx v%s", VERSION_STRING); + printf("\nCopyright (c) 2021 .NET Foundation and Contributors\n"); + printf("\nCLR_RT_HeapBlock: %d\r\n\n", sizeof(CLR_RT_HeapBlock)); + printf("\nCLR_RT_HeapBlock: %d\r\n\n", sizeof(CLR_RT_HeapBlock_Raw)); +#endif + + // prepare -load + d = opendir(path.c_str()); + while ((dir = readdir(d)) != NULL) { + if (strstr(dir->d_name, ".pe") != NULL) { + args.push_back(dir->d_name); + } + } + closedir(d); + + if(!CPU_GPIO_Initialize()) + { + printf("WARNING! not possible initialize GPIO subsystem (permissions?)\n"); + } + + nanoHAL_Initialize(); + + CLR_SETTINGS clrSettings; + memset(&clrSettings, 0, sizeof(clrSettings)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = false; + + // fill arguments from command line + clrSettings.StartArgs.resize(args.size() * 2); + + for (; i < args.size(); i++) { + std::string argstring = std::string("-load"); + std::string argstringAss = std::string(path.c_str() + args.at(i)); + clrSettings.StartArgs[i+i] = argstring; + clrSettings.StartArgs[(i+i)+1] = argstringAss; + +#if defined(DEBUG) + printf("passing argument :: %s %s\n", argstring.c_str(), argstringAss.c_str()); +#endif + } + + args.clear(); + args.shrink_to_fit(); + + ClrStartup(clrSettings); + +#if defined(DEBUG) + CLR_Debug::Printf("Exiting.\r\n"); +#endif + + return 0; +} + +#if defined(__nuttx__) +} +#endif diff --git a/posix/target/CLRStartup.cpp b/posix/target/CLRStartup.cpp new file mode 100644 index 00000000..b0cd7c15 --- /dev/null +++ b/posix/target/CLRStartup.cpp @@ -0,0 +1,699 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "include/stdafx.h" + +#if defined(_WIN32) + +#endif + +//////////////////////////////////////////////////////////////////////////////// + +struct Settings : CLR_RT_ParseOptions +{ + CLR_SETTINGS m_clrOptions; + CLR_RT_ParseOptions::BufferMap m_assemblies; + bool m_fInitialized; + + //--// + + HRESULT Initialize(CLR_SETTINGS params) + { + NANOCLR_HEADER(); + + m_clrOptions = params; + +#if defined(PLATFORM_WINDOWS_EMULATOR) + g_CLR_RT_ExecutionEngine.m_fPerformGarbageCollection = params.PerformGarbageCollection; + g_CLR_RT_ExecutionEngine.m_fPerformHeapCompaction = params.PerformHeapCompaction; + + CLR_UINT32 clockFrequencyBaseline = 27000000; + CLR_UINT32 clockFrequency = CPU_SystemClock(); + double clockFrequencyRatio = 1; + + if (clockFrequency > 0) + { + clockFrequencyRatio = (double)clockFrequencyBaseline / (double)clockFrequency; + } + + g_HAL_Configuration_Windows.ProductType = HAL_Configuration_Windows::Product_Aux; + g_HAL_Configuration_Windows.SlowClockPerSecond = 32768; + g_HAL_Configuration_Windows.TicksPerMethodCall = (CLR_UINT64)(45.0 * clockFrequencyRatio); + g_HAL_Configuration_Windows.TicksPerOpcode = (CLR_UINT64)(5.0 * clockFrequencyRatio); + g_HAL_Configuration_Windows.GraphHeapEnabled = false; +#endif + + NANOCLR_CHECK_HRESULT(CLR_RT_ExecutionEngine::CreateInstance()); +#if !defined(BUILD_RTM) + CLR_Debug::Printf("Created EE.\r\n"); +#endif + +#if !defined(BUILD_RTM) + if (params.WaitForDebugger) + { +#if defined(_WIN32) || defined(__linux__) || defined(__nuttx__) + CLR_EE_DBG_SET(Enabled); +#endif + CLR_EE_DBG_SET(Stopped); + } +#endif + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.StartHardware()); +#if !defined(BUILD_RTM) + CLR_Debug::Printf("Started Hardware.\r\n"); +#endif + + CLR_DBG_Debugger::Debugger_Discovery(); + + m_fInitialized = true; + + NANOCLR_NOCLEANUP(); + } + + HRESULT LoadAssembly(const CLR_RECORD_ASSEMBLY *header, CLR_RT_Assembly *&assm) + { + NANOCLR_HEADER(); + + const CLR_RT_NativeAssemblyData *pNativeAssmData; + + NANOCLR_CHECK_HRESULT(CLR_RT_Assembly::CreateInstance(header, assm)); + + // Get handlers for native functions in assembly + pNativeAssmData = GetAssemblyNativeData(assm->m_szName); + + // If pNativeAssmData not NULL- means this assembly has native calls and there is pointer to table with native + // calls. + if (pNativeAssmData != NULL) + { + // First verify that check sum in assembly object matches hardcoded check sum. + if (assm->m_header->nativeMethodsChecksum != pNativeAssmData->m_checkSum) + { + CLR_Debug::Printf( + "\r\n\r\n***********************************************************************\r\n"); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("* ERROR!!!! Firmware version does not match managed code version!!!! *\r\n"); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf( + "* Invalid native checksum: %s 0x%08X!=0x%08X *\r\n", + assm->m_szName, + assm->m_header->nativeMethodsChecksum, + pNativeAssmData->m_checkSum); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("***********************************************************************\r\n"); + + NANOCLR_SET_AND_LEAVE(CLR_E_ASSM_WRONG_CHECKSUM); + } + + // Assembly has valid pointer to table with native methods. Save it. + assm->m_nativeCode = (const CLR_RT_MethodHandler *)pNativeAssmData->m_pNativeMethods; + } + g_CLR_RT_TypeSystem.Link(assm); + NANOCLR_NOCLEANUP(); + } + + HRESULT Load() + { +#if defined(DEBUG) + CLR_Debug::Printf("Let's Load\n"); +#endif + NANOCLR_HEADER(); + + // clear flag (in case EE wasn't restarted) + CLR_EE_DBG_CLR(StateResolutionFailed); + + NANOCLR_CHECK_HRESULT(ProcessOptions(m_clrOptions.StartArgs)); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf("Loading Assemblies.\r\n"); +#endif + + for (CLR_RT_ParseOptions::BufferMapIter it = m_assemblies.begin(); it != m_assemblies.end(); it++) + { + CLR_RT_Assembly *assm; + const CLR_RT_Buffer *buffer = (const CLR_RT_Buffer *)it->second; + const CLR_RECORD_ASSEMBLY *header = (CLR_RECORD_ASSEMBLY *)&(*buffer)[0]; + + // Creates instance of assembly, sets pointer to native functions, links to g_CLR_RT_TypeSystem + NANOCLR_CHECK_HRESULT(LoadAssembly(header, assm)); + } + + // don't load assemblies because we don't have any deployment storage +#if !defined(BUILD_RTM) +// CLR_Debug::Printf("Loading Deployment Assemblies.\r\n"); +#endif + + // LoadDeploymentAssemblies(BlockUsage_DEPLOYMENT); + + //--// + +#if !defined(BUILD_RTM) + CLR_Debug::Printf("Resolving.\r\n"); +#endif + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.ResolveAll()); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.PrepareForExecution()); + +#if defined(NANOCLR_PROFILE_HANDLER) + CLR_PROF_Handler::Calibrate(); +#endif + + NANOCLR_CLEANUP(); + +#if !defined(BUILD_RTM) + if (FAILED(hr)) + { +#if defined(__linux__) + print_trace(); +#endif + CLR_Debug::Printf("Error: %08x\r\n", hr); + + if (hr == CLR_E_TYPE_UNAVAILABLE) + { + // exception occurred during type resolution + CLR_EE_DBG_SET(StateResolutionFailed); + } + } +#endif + + NANOCLR_CLEANUP_END(); + } + + HRESULT CheckKnownAssembliesForNonXIP(char **start, char **end) + { + //--// + NANOCLR_HEADER(); + + BlockStorageDevice *device; + ByteAddress datByteAddress; + unsigned int datSize = ROUNDTOMULTIPLE((unsigned int)(*end) - (unsigned int)(*start), CLR_UINT32); + + if (BlockStorageList_FindDeviceForPhysicalAddress(&device, (unsigned int)(*start), &datByteAddress) && + device != NULL) + { + const DeviceBlockInfo *deviceInfo = BlockStorageDevice_GetDeviceInfo(device); + + if (deviceInfo->Attribute & MediaAttribute_SupportsXIP) + { + unsigned char *datAssembliesBuffer = + (unsigned char *)CLR_RT_Memory::Allocate_And_Erase(datSize, CLR_RT_HeapBlock ::HB_Unmovable); + CHECK_ALLOCATION(datAssembliesBuffer); + + if (!BlockStorageDevice_Read(device, datByteAddress, datSize, datAssembliesBuffer)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + *start = (char *)datAssembliesBuffer; + *end = (char *)((unsigned int)datAssembliesBuffer + (unsigned int)datSize); + } + } + + // else data in RAM + NANOCLR_NOCLEANUP(); + } + + HRESULT LoadKnownAssemblies(char *start, char *end) + { + //--// + NANOCLR_HEADER(); + char *assStart = start; + char *assEnd = end; + const CLR_RECORD_ASSEMBLY *header; + + NANOCLR_CHECK_HRESULT(CheckKnownAssembliesForNonXIP(&assStart, &assEnd)); +#if !defined(BUILD_RTM) + CLR_Debug::Printf(" Loading start at %x, end %x\r\n", (unsigned int)assStart, (unsigned int)assEnd); +#endif + + g_buildCRC = SUPPORT_ComputeCRC(assStart, (unsigned int)assEnd - (unsigned int)assStart, 0); + + header = (const CLR_RECORD_ASSEMBLY *)assStart; + + while ((char *)header + sizeof(CLR_RECORD_ASSEMBLY) < assEnd && header->GoodAssembly()) + { + CLR_RT_Assembly *assm; + + // Creates instance of assembly, sets pointer to native functions, links to g_CLR_RT_TypeSystem + NANOCLR_CHECK_HRESULT(LoadAssembly(header, assm)); + + header = (const CLR_RECORD_ASSEMBLY *)ROUNDTOMULTIPLE((size_t)header + header->TotalSize(), CLR_UINT32); + } + + NANOCLR_NOCLEANUP(); + } + + HRESULT ContiguousBlockAssemblies(BlockStorageStream stream, bool isXIP) + { + NANOCLR_HEADER(); + + const CLR_RECORD_ASSEMBLY *header; + unsigned char *assembliesBuffer; + signed int headerInBytes = sizeof(CLR_RECORD_ASSEMBLY); + unsigned char *headerBuffer = NULL; + + if (!isXIP) + { + headerBuffer = (unsigned char *)CLR_RT_Memory::Allocate(headerInBytes, true); + CHECK_ALLOCATION(headerBuffer); + CLR_RT_Memory::ZeroFill(headerBuffer, headerInBytes); + } + + while (TRUE) + { + if (!BlockStorageStream_Read(&stream, &headerBuffer, headerInBytes)) + break; + + header = (const CLR_RECORD_ASSEMBLY *)headerBuffer; + + // check header first before read + if (!header->GoodHeader()) + { + break; + } + + unsigned int AssemblySizeInByte = ROUNDTOMULTIPLE(header->TotalSize(), CLR_UINT32); + + if (!isXIP) + { + // read the assemblies + assembliesBuffer = (unsigned char *)CLR_RT_Memory::Allocate_And_Erase( + AssemblySizeInByte, + CLR_RT_HeapBlock ::HB_Unmovable); + + if (!assembliesBuffer) + { + // release the headerbuffer which has being used and leave + CLR_RT_Memory::Release(headerBuffer); + + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + } + + BlockStorageStream_Seek(&stream, -headerInBytes, BlockStorageStream_SeekCurrent); + + if (!BlockStorageStream_Read(&stream, &assembliesBuffer, AssemblySizeInByte)) + break; + + header = (const CLR_RECORD_ASSEMBLY *)assembliesBuffer; + + if (!header->GoodAssembly()) + { + if (!isXIP) + CLR_RT_Memory::Release(assembliesBuffer); + break; + } + + // we have good Assembly + CLR_RT_Assembly *assm; + + // Creates instance of assembly, sets pointer to native functions, links to g_CLR_RT_TypeSystem + if (FAILED(LoadAssembly(header, assm))) + { + if (!isXIP) + CLR_RT_Memory::Release(assembliesBuffer); + break; + } + assm->m_flags |= CLR_RT_Assembly::Deployed; + } + if (!isXIP) + CLR_RT_Memory::Release(headerBuffer); + + NANOCLR_NOCLEANUP(); + } + + HRESULT LoadDeploymentAssemblies(unsigned int memoryUsage) + { + NANOCLR_HEADER(); + + BlockStorageStream stream; + const DeviceBlockInfo *deviceInfo; + + // find the block + if (!BlockStorageStream_Initialize(&stream, memoryUsage)) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf("ERROR: Could not find device for DEPLOYMENT usage\r\n"); +#endif + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + + do + { + deviceInfo = BlockStorageDevice_GetDeviceInfo(stream.Device); + + ContiguousBlockAssemblies(stream, (deviceInfo->Attribute & MediaAttribute_SupportsXIP)); + } while (BlockStorageStream_NextStream(&stream)); + + NANOCLR_NOCLEANUP(); + } + + void Cleanup() + { + CLR_RT_ExecutionEngine::DeleteInstance(); + + memset(&g_CLR_RT_ExecutionEngine, 0, sizeof(g_CLR_RT_ExecutionEngine)); + memset(&g_CLR_RT_WellKnownTypes, 0, sizeof(g_CLR_RT_WellKnownTypes)); + memset(&g_CLR_RT_WellKnownMethods, 0, sizeof(g_CLR_RT_WellKnownMethods)); + memset(&g_CLR_RT_TypeSystem, 0, sizeof(g_CLR_RT_TypeSystem)); + memset(&g_CLR_RT_EventCache, 0, sizeof(g_CLR_RT_EventCache)); + memset(&g_CLR_RT_GarbageCollector, 0, sizeof(g_CLR_RT_GarbageCollector)); + memset(&g_CLR_HW_Hardware, 0, sizeof(g_CLR_HW_Hardware)); + + m_fInitialized = false; + } + + Settings() + { + m_fInitialized = false; +#if defined(_WIN32) || defined(__linux__) || defined(__nuttx__) + BuildOptions(); +#endif + } + +#if defined(_WIN32) || defined(__linux__) || defined(__nuttx__) + ~Settings() + { + for (CLR_RT_ParseOptions::BufferMapIter it = m_assemblies.begin(); it != m_assemblies.end(); it++) + { + delete it->second; + } + + int mSize = m_commands.size(); + + for (int i = 0; i < mSize; i++) + { + Command* cmd = m_commands.front(); + int cmdSize = cmd->m_params.size(); + + for (int j = 0; j < cmdSize; j++) + { + delete cmd->m_params.back(); + cmd->m_params.pop_back(); + } + + delete cmd; + m_commands.pop_front(); + } + + m_assemblies.clear(); // CLR_RT_ParseOptions::BufferMap m_assemblies; + } + + struct Command_Call : CLR_RT_ParseOptions::Command + { + typedef HRESULT (Settings::*FPN)(CLR_RT_ParseOptions::ParameterList *params); + + Settings &m_parent; + FPN m_call; + + Command_Call(Settings &parent, FPN call, const char *szName, const char *szDescription) + : CLR_RT_ParseOptions::Command(szName, szDescription), m_parent(parent), m_call(call) + { + } + + virtual HRESULT Execute() + { + return (m_parent.*m_call)(&m_params); + } + }; + +#define PARAM_GENERIC(parm1Name, parm1Desc) \ + param = new CLR_RT_ParseOptions::Parameter_Generic(parm1Name, parm1Desc); \ + cmd->m_params.push_back(param) +#define OPTION_CALL(fpn, optName, optDesc) \ + cmd = new Command_Call(*this, &Settings::fpn, optName, optDesc); \ + m_commands.push_back(cmd) +#define PARAM_EXTRACT_STRING(lst, index) ((CLR_RT_ParseOptions::Parameter_Generic *)(*lst)[index])->m_data.c_str() + + void BuildOptions() + { + CLR_RT_ParseOptions::Command *cmd; + CLR_RT_ParseOptions::Parameter *param; + + OPTION_CALL(Cmd_Load, "-load", "Loads an assembly formatted for nanoCLR"); + PARAM_GENERIC("", "File to load"); + + OPTION_CALL(Cmd_LoadDatabase, "-loadDatabase", "Loads a set of assemblies"); + PARAM_GENERIC("", "Image to load"); + + OPTION_CALL(Cmd_Resolve, "-resolve", "Tries to resolve cross-assembly references"); + } + + HRESULT CheckAssemblyFormat(CLR_RECORD_ASSEMBLY *header, const char *src) + { + NANOCLR_HEADER(); + + if (header->GoodAssembly() == false) + { + printf("Invalid assembly format for '%s': ", src); + for (int i = 0; i < sizeof(header->marker); i++) + { + printf("%02x", header->marker[i]); + } + printf("\n"); + + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + NANOCLR_NOCLEANUP(); + } + + HRESULT Cmd_Load(CLR_RT_ParseOptions::ParameterList *params = NULL) + { + NANOCLR_HEADER(); + + const char *szName = PARAM_EXTRACT_STRING(params, 0); + CLR_RT_Buffer *buffer = new CLR_RT_Buffer(); + CLR_RECORD_ASSEMBLY *header; + + NANOCLR_CHECK_HRESULT(CLR_RT_FileStore::LoadFile(szName, *buffer)); + + header = (CLR_RECORD_ASSEMBLY *)&(*buffer)[0]; + NANOCLR_CHECK_HRESULT(CheckAssemblyFormat(header, szName)); + + m_assemblies[szName] = buffer; + + NANOCLR_CLEANUP(); + + if (FAILED(hr)) + { + delete buffer; + } + + NANOCLR_CLEANUP_END(); + } + + HRESULT Cmd_LoadDatabase(CLR_RT_ParseOptions::ParameterList *params = NULL) + { + NANOCLR_HEADER(); + + if (!m_fInitialized) + { + CLR_RT_ExecutionEngine::CreateInstance(); + } + + { + const char *szFile = PARAM_EXTRACT_STRING(params, 0); + CLR_RT_Buffer buffer; + CLR_RECORD_ASSEMBLY *header; + CLR_RECORD_ASSEMBLY *headerEnd; + std::string strName; + + NANOCLR_CHECK_HRESULT(CLR_RT_FileStore::LoadFile(szFile, buffer)); + + header = (CLR_RECORD_ASSEMBLY *)&buffer[0]; + headerEnd = (CLR_RECORD_ASSEMBLY *)&buffer[buffer.size() - 1]; + + while (header + 1 <= headerEnd && header->GoodAssembly()) + { + CLR_RT_Buffer *bufferSub = new CLR_RT_Buffer(); + CLR_RECORD_ASSEMBLY *headerSub; + CLR_RT_Assembly *assm; + + bufferSub->resize(header->TotalSize()); + + headerSub = (CLR_RECORD_ASSEMBLY *)&(*bufferSub)[0]; + + if ((CLR_UINT8 *)header + header->TotalSize() > (CLR_UINT8 *)headerEnd) + { + // checksum passed, but not enough data in assembly + _ASSERTE(FALSE); + delete bufferSub; + break; + } + memcpy(headerSub, header, header->TotalSize()); + + m_assemblies[strName] = bufferSub; + + if (FAILED(hr = CLR_RT_Assembly::CreateInstance(headerSub, assm))) + { + delete bufferSub; + break; + } + + CLR_RT_UnicodeHelper::ConvertFromUTF8(assm->m_szName, strName); + m_assemblies[strName] = bufferSub; + + assm->DestroyInstance(); + + header = (CLR_RECORD_ASSEMBLY *)ROUNDTOMULTIPLE((size_t)header + header->TotalSize(), CLR_UINT32); + } + } + + NANOCLR_CLEANUP(); + + if (!m_fInitialized) + { + CLR_RT_ExecutionEngine::DeleteInstance(); + } + + NANOCLR_CLEANUP_END(); + } + + HRESULT Cmd_Resolve(CLR_RT_ParseOptions::ParameterList *params = NULL) + { + NANOCLR_HEADER(); + + bool fError = false; + + NANOCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + const CLR_RECORD_ASSEMBLYREF *src = (const CLR_RECORD_ASSEMBLYREF *)pASSM->GetTable(TBL_AssemblyRef); + for (int i = 0; i < pASSM->m_pTablesSize[TBL_AssemblyRef]; i++, src++) + { + const char *szName = pASSM->GetString(src->name); + + if (g_CLR_RT_TypeSystem.FindAssembly(szName, &src->version, true) == NULL) + { + printf( + "Missing assembly: %s (%d.%d.%d.%d)\n", + szName, + src->version.iMajorVersion, + src->version.iMinorVersion, + src->version.iBuildNumber, + src->version.iRevisionNumber); + + fError = true; + } + } + } + NANOCLR_FOREACH_ASSEMBLY_END(); + + if (fError) + NANOCLR_SET_AND_LEAVE(CLR_E_ENTRY_NOT_FOUND); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.ResolveAll()); + + NANOCLR_NOCLEANUP(); + } +#endif //#if defined(_WIN32) +}; + +//--// + +#if defined(_WIN32) || defined(__linux__) || defined(__nuttx__) +HRESULT ClrLoadPE(Settings *s_ClrSettings, const char *szPeFilePath) +{ + CLR_Debug::Printf("Let's load %s\n", szPeFilePath); + CLR_RT_StringVector vec; + + vec.push_back("-load"); + + vec.push_back(szPeFilePath); + + return s_ClrSettings->ProcessOptions(vec); +} + +HRESULT ClrLoadDAT(Settings *s_ClrSettings, const char *szDatFilePath) +{ + CLR_RT_StringVector vec; + + vec.push_back("-loadDatabase"); + + vec.push_back(szDatFilePath); + + return s_ClrSettings->ProcessOptions(vec); +} +#endif + +void ClrStartup(CLR_SETTINGS params) +{ + NATIVE_PROFILE_CLR_STARTUP(); + Settings s_ClrSettings; + ASSERT(sizeof(CLR_RT_HeapBlock_Raw) == sizeof(CLR_RT_HeapBlock)); + bool softReboot; + + do + { + softReboot = false; + + CLR_RT_Assembly::InitString(); + CLR_RT_Memory::Reset(); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf("Starting...\r\n"); +#endif + + HRESULT hr; + + if (SUCCEEDED(hr = s_ClrSettings.Initialize(params))) + { + if (SUCCEEDED(hr = s_ClrSettings.Load())) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf("Ready.\r\n"); +#endif + + (void)g_CLR_RT_ExecutionEngine.Execute(NULL, params.MaxContextSwitches); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf("Done.\r\n"); +#endif + } + } + + // process setting of power mode, if reboot was requested along with a power mode "higher" then + // PowerLevel__Active + if (CLR_EE_REBOOT_IS(ClrOnly) && g_CLR_HW_Hardware.m_powerLevel > PowerLevel__Active) + { + CPU_SetPowerMode(g_CLR_HW_Hardware.m_powerLevel); + } + + if (CLR_EE_DBG_IS_NOT(RebootPending)) + { +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_EE_DBG_SET_MASK(StateProgramExited, StateMask); + CLR_EE_DBG_EVENT_BROADCAST(CLR_DBG_Commands::c_Monitor_ProgramExit, 0, NULL, WP_Flags_c_NonCritical); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + if (params.EnterDebuggerLoopAfterExit) + { + CLR_DBG_Debugger::Debugger_WaitForCommands(); + } + } + + // DO NOT USE 'ELSE IF' here because the state can change in Debugger_WaitForCommands() call + + if (CLR_EE_DBG_IS(RebootPending)) + { + if (CLR_EE_REBOOT_IS(ClrOnly)) + { + softReboot = true; + + params.WaitForDebugger = CLR_EE_REBOOT_IS(WaitForDebugger); + + s_ClrSettings.Cleanup(); + + // nanoHAL_Uninitialize(); + + // re-init the hal for the reboot (initially it is called in bootentry) + // nanoHAL_Initialize(); + } + else + { + CPU_Reset(); + } + } + } while (softReboot); +} diff --git a/posix/target/FileStore_Win32.cpp b/posix/target/FileStore_Win32.cpp new file mode 100644 index 00000000..5f99f9d1 --- /dev/null +++ b/posix/target/FileStore_Win32.cpp @@ -0,0 +1,273 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "include/stdafx.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_FileStore::LoadFile(const char *szFile, CLR_RT_Buffer &vec) +{ + NANOCLR_HEADER(); + + // TODO: port to linux + long size; + const char *str = szFile; + /*char *str = new char[4046]; + wcstombs(str, szFile, wcslen(szFile));*/ + + FILE *stream = fopen(str, "rb"); + //if (_wfopen_s(&stream, szFile, L"rb") != 0) + if (stream == NULL) + { + printf("Cannot open '%s'!\n", szFile); + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + // WTF 🤣 + /*********/ fseek(stream, 0, SEEK_END); + size = ftell(stream); + /*********/ fseek(stream, 0, SEEK_SET); + + vec.resize(size); + + if (vec.size() && fread(&vec[0], vec.size(), 1, stream) != 1) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + NANOCLR_CLEANUP(); + + if (stream) + { + fclose(stream); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_FileStore::SaveFile(const char *szFile, const CLR_RT_Buffer &vec) +{ + NANOCLR_HEADER(); + + const CLR_UINT8 *buf = NULL; + size_t size = vec.size(); + + if (size > 0) + { + buf = &vec[0]; + } + + NANOCLR_SET_AND_LEAVE(SaveFile(szFile, buf, size)); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_FileStore::SaveFile(const char *szFile, const CLR_UINT8 *buf, size_t size) +{ + NANOCLR_HEADER(); + + // TODO: port to linux + const char *str = szFile; + /*char *str = new char[4046]; + wcstombs(str, szFile, wcslen(szFile));*/ + + FILE *stream = fopen(str, "rb"); + //if (_wfopen_s(&stream, szFile, L"rb") != 0) + if (stream != NULL) + { + printf("Cannot open '%s' for writing!\n", str); + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + if (buf != NULL && size != 0) + { + if (fwrite(buf, size, 1, stream) != 1) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + } + + NANOCLR_CLEANUP(); + + if (stream) + { + fclose(stream); + } + + NANOCLR_CLEANUP_END(); +} + +//--// + +HRESULT CLR_RT_FileStore::ExtractTokensFromFile( + const char *szFileName, + std::vector &vec, + const char *separators, + bool fNoComments) +{ + NANOCLR_HEADER(); + + CLR_RT_Buffer buf; + + NANOCLR_CHECK_HRESULT(LoadFile(szFileName, buf)); + + ExtractTokens(buf, vec, separators, fNoComments); + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_FileStore::ExtractTokens( + const CLR_RT_Buffer &buf, + CLR_RT_StringVector &vec, + const char *separators, + bool fNoComments) +{ + std::string tmp; + char *szBufA = NULL; + char *szBufW = NULL; + const char *src; + size_t len; + + if (buf.size() == 0) + { + return; + } + else if (buf.size() >= 2 && buf[0] == 0xFF && buf[1] == 0xFE) + { + len = (buf.size() - 2) / sizeof(char); + + src = (const char *)&buf[2]; + } + else + { + len = buf.size() / sizeof(char); + + szBufA = new char[len + 1]; + memcpy(szBufA, &buf[0], len); + szBufA[len] = 0; + CLR_RT_UnicodeHelper::ConvertFromUTF8(szBufA, tmp); + + src = tmp.c_str(); + len = tmp.size(); + } + + //--// + + szBufW = new char[len + 1]; + memcpy(szBufW, src, len * sizeof(char)); + szBufW[len] = 0; + + vec.reserve(len / 60); + + ExtractTokensFromBuffer(szBufW, vec, separators, fNoComments); + + //--// + + delete[] szBufW; + delete[] szBufA; +} + +void CLR_RT_FileStore::ExtractTokensFromBuffer( + char *szLine, + CLR_RT_StringVector &vec, + const char *separators, + bool fNoComments) +{ + while (*szLine) + { + char *szNextLine = szLine; + + while (*szNextLine) + { + if (*szNextLine == '\r' || *szNextLine == '\n') + { + while (*szNextLine == '\r' || *szNextLine == '\n') + { + *szNextLine++ = 0; + } + + break; + } + + szNextLine++; + } + + if (fNoComments == false || szLine[0] != '#') + { + CLR_RT_FileStore::ExtractTokensFromString(szLine, vec, separators); + } + + szLine = szNextLine; + } +} + +void CLR_RT_FileStore::ExtractTokensFromString( + const char *szLine, + CLR_RT_StringVector &vec, + const char *separators) +{ + if (separators) + { + while (szLine[0] && strchr(separators, szLine[0])) + szLine++; + + while (szLine[0]) + { + char token[2048]; + char tokenExpanded[2048]; + bool fQuote = false; + size_t pos; + + for (pos = 0; pos < MAXSTRLEN(token);) + { + char c = *szLine++; + + if (c == 0) + { + szLine--; + break; + } + + if (fQuote) + { + if (c == '\\') + { + c = *szLine++; + ; + } + else if (c == '"') + { + fQuote = false; + continue; + } + } + else if (c == '"') + { + fQuote = true; + continue; + } + else + { + if (strchr(separators, c)) + break; + } + + token[pos++] = c; + } + token[pos] = 0; + + // TODO: port to linux + //::ExpandEnvironmentStringsW(token, tokenExpanded, MAXSTRLEN(tokenExpanded)); + vec.push_back(tokenExpanded); + + while (szLine[0] && strchr(separators, szLine[0])) + szLine++; + } + } + else + { + vec.push_back(szLine); + } +} diff --git a/posix/target/Generated/CLR_RT_InteropAssembliesTable.cpp b/posix/target/Generated/CLR_RT_InteropAssembliesTable.cpp new file mode 100644 index 00000000..0c1abf5e --- /dev/null +++ b/posix/target/Generated/CLR_RT_InteropAssembliesTable.cpp @@ -0,0 +1,31 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#include "include/stdafx.h" + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib; +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_System_Math; +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_System_Collections; +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_System_Text; +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Native; +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_ResourceManager; + +// nanoFramework class libraries declarations +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Events; +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Events_EventSink_DriverProcs; + +const CLR_RT_NativeAssemblyData *g_CLR_InteropAssembliesNativeData[] = { + &g_CLR_AssemblyNative_mscorlib, + &g_CLR_AssemblyNative_System_Math, + &g_CLR_AssemblyNative_nanoFramework_System_Collections, + &g_CLR_AssemblyNative_nanoFramework_System_Text, + &g_CLR_AssemblyNative_nanoFramework_ResourceManager, + &g_CLR_AssemblyNative_nanoFramework_Runtime_Native, + &g_CLR_AssemblyNative_nanoFramework_Runtime_Events, + &g_CLR_AssemblyNative_nanoFramework_Runtime_Events_EventSink_DriverProcs, + &g_CLR_AssemblyNative_System_Device_Gpio, + NULL}; + +uint16_t g_CLR_InteropAssembliesCount = ARRAYSIZE(g_CLR_InteropAssembliesNativeData) - 1; diff --git a/posix/target/Memory.cpp b/posix/target/Memory.cpp new file mode 100644 index 00000000..71e0d769 --- /dev/null +++ b/posix/target/Memory.cpp @@ -0,0 +1,65 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "include/stdafx.h" + +// using namespace Microsoft::SPOT::Emulator; + +// TODO: port to linux + +// This is good for get virtual memory from Linux + +// From minheap.cpp +// static unsigned char *s_Memory_Start = NULL; +// static unsigned int s_Memory_Length = 1024 * 1024 * 10; + +// void HeapLocation(unsigned char *&BaseAddress, unsigned int &SizeInBytes) +// { +// if (!s_Memory_Start) +// { +// // TODO: port to linux +// /*s_Memory_Start = +// (unsigned char *)::VirtualAlloc(NULL, s_Memory_Length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);*/ +// s_Memory_Start = +// (unsigned char *) mmap(NULL, s_Memory_Length, PROT_READ | PROT_WRITE, MAP_32BIT | MAP_SHARED | MAP_ANON, -1, 0); + +// if (s_Memory_Start) +// { +// memset(s_Memory_Start, 0x0, s_Memory_Length); +// } + +// HalSystemConfig.RAM1.Base = (unsigned int)(size_t)s_Memory_Start; +// HalSystemConfig.RAM1.Size = (unsigned int)(size_t)s_Memory_Length; +// } + +// BaseAddress = s_Memory_Start; +// SizeInBytes = s_Memory_Length; +// } + +// TODO: port to nuttx + +// this is to simulate the same behavior from nuttx + +static unsigned char *s_Memory_Start = NULL; +static unsigned int s_Memory_Length = 64*1024; + +#define MANAGED_HEAP_SIZE (64*1024) +uint32_t managedHeap[MANAGED_HEAP_SIZE/ sizeof(uint32_t)]; + +void HeapLocation(unsigned char *&BaseAddress, unsigned int &SizeInBytes) +{ + if (!s_Memory_Start) + { + // static heap memory + s_Memory_Start = (unsigned char*)&managedHeap; + s_Memory_Length = sizeof(managedHeap); + + HalSystemConfig.RAM1.Base = (unsigned int)(size_t)s_Memory_Start; + HalSystemConfig.RAM1.Size = (unsigned int)(size_t)s_Memory_Length; + } + + BaseAddress = s_Memory_Start; + SizeInBytes = s_Memory_Length; +} diff --git a/posix/target/PAL/COMDirector_stubs.cpp b/posix/target/PAL/COMDirector_stubs.cpp new file mode 100644 index 00000000..ead4accf --- /dev/null +++ b/posix/target/PAL/COMDirector_stubs.cpp @@ -0,0 +1,83 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "include/stdafx.h" +#include +#include + +#define NATIVE_PROFILE_PAL_COM() + +////////////////////////////////////////////////////////////////////////////////// + +__nfweak bool DebuggerPort_Initialize(COM_HANDLE ComPortNum) +{ + NATIVE_PROFILE_PAL_COM(); + return true; +} + +__nfweak bool DebuggerPort_Uninitialize(COM_HANDLE ComPortNum) +{ + NATIVE_PROFILE_PAL_COM(); + return true; +} + +__nfweak int DebuggerPort_Write(COM_HANDLE ComPortNum, const char *Data, size_t size) +{ + NATIVE_PROFILE_PAL_COM(); + return DebuggerPort_Write(ComPortNum, Data, size, COM_MAX_RETRIES); +} + +__nfweak int DebuggerPort_Write(COM_HANDLE ComPortNum, const char *Data, size_t size, int maxRetries) +{ + NATIVE_PROFILE_PAL_COM(); + return 0; +} + +__nfweak int DebuggerPort_Read(COM_HANDLE ComPortNum, char *Data, size_t size) +{ + NATIVE_PROFILE_PAL_COM(); + return 0; +} + +__nfweak bool DebuggerPort_Flush(COM_HANDLE ComPortNum) +{ + NATIVE_PROFILE_PAL_COM(); + return true; +} + +__nfweak bool DebuggerPort_IsSslSupported(COM_HANDLE ComPortNum) +{ + NATIVE_PROFILE_PAL_COM(); + return FALSE; +} + +__nfweak bool DebuggerPort_UpgradeToSsl(COM_HANDLE ComPortNum, unsigned int flags) +{ + NATIVE_PROFILE_PAL_COM(); + return FALSE; +} + +__nfweak bool DebuggerPort_IsUsingSsl(COM_HANDLE ComPortNum) +{ + NATIVE_PROFILE_PAL_COM(); + return FALSE; +} + +////////////////////////////////////////////////////////////////////////////////// + +void CPU_InitializeCommunication() +{ + NATIVE_PROFILE_PAL_COM(); +} + +void CPU_UninitializeCommunication() +{ + NATIVE_PROFILE_PAL_COM(); +} + +void CPU_ProtectCommunicationGPIOs(bool On) +{ + NATIVE_PROFILE_PAL_COM(); +} diff --git a/posix/target/PAL/CPU_Gpio_Linux.cpp b/posix/target/PAL/CPU_Gpio_Linux.cpp new file mode 100644 index 00000000..2b5c4748 --- /dev/null +++ b/posix/target/PAL/CPU_Gpio_Linux.cpp @@ -0,0 +1,195 @@ + +#include + +#if defined(__linux__) && defined(__gpio) + +bool CPU_GPIO_Initialize() +{ + // for now supporting only bank 0 + _chip = gpiod_chip_open_by_number(0); + + if (_chip == NULL) + return false; + + return true; +} + +bool CPU_GPIO_Uninitialize() +{ + // no need to unitialize + return true; +} + +void CPU_GPIO_DisablePin(GPIO_PIN Pin, GpioPinDriveMode driveMode, + uint32_t alternateFunction) +{ + GLOBAL_LOCK(); + CPU_GPIO_SetDriveMode(Pin, driveMode); + + // disable line + gpiod_line_release(pinLineStored[Pin]); + + GLOBAL_UNLOCK(); + + CPU_GPIO_ReservePin(Pin, false); +} + +bool CPU_GPIO_EnableOutputPin(GPIO_PIN Pin, GpioPinValue InitialState, + GpioPinDriveMode driveMode) +{ + // check not an output drive mode + if (driveMode < (int)GpioPinDriveMode_Output) + return false; + + if (CPU_GPIO_SetDriveMode(Pin, driveMode) == false) + return false; + + CPU_GPIO_SetPinState(Pin, InitialState); + + return true; +} + +bool CPU_GPIO_EnableInputPin( + GPIO_PIN pinNumber, + CLR_UINT64 debounceTimeMilliseconds, + GPIO_INTERRUPT_SERVICE_ROUTINE pin_ISR, + void *isr_Param, + GPIO_INT_EDGE intEdge, + GpioPinDriveMode driveMode) +{ + // Check Input drive mode + if (driveMode >= (int)GpioPinDriveMode_Output) + { + return false; + } + + if (pin_ISR != NULL) { + switch (intEdge) + { + case GPIO_INT_EDGE_LOW: + case GPIO_INT_LEVEL_LOW: + case GPIO_INT_EDGE_HIGH: + case GPIO_INT_LEVEL_HIGH: + case GPIO_INT_EDGE_BOTH: + // TODO: IRQ callback not implemented + return false; + break; + + default: + break; + } + } + + if (!CPU_GPIO_SetDriveMode(pinNumber, driveMode)) + { + return false; + } + + // not implemented :: debounce time + // TODO + return true; +} + +GpioPinValue CPU_GPIO_GetPinState(GPIO_PIN Pin) +{ + if (pinDirStored[Pin] == GpioPinDriveMode_Output) + return pinLineValue[Pin]; + + int val = gpiod_line_get_value(pinLineStored[Pin]); + return val == 1 ? GpioPinValue_High : GpioPinValue_Low; +} + +void CPU_GPIO_SetPinState(GPIO_PIN Pin, GpioPinValue PinState) +{ + pinLineValue[Pin] = PinState; + int val = gpiod_line_set_value(pinLineStored[Pin], PinState); +} + +void CPU_GPIO_TogglePinState(GPIO_PIN pinNumber) +{ + GpioPinValue value = CPU_GPIO_GetPinState(pinNumber); + + switch (value) + { + case GpioPinValue_High: + CPU_GPIO_SetPinState(pinNumber, GpioPinValue_Low); + break; + case GpioPinValue_Low: + CPU_GPIO_SetPinState(pinNumber, GpioPinValue_High); + break; + default: + break; + } +} + +bool IsValidGpioPin(GPIO_PIN pinNumber) +{ + return (pinNumber <= GPIO_MAX_PIN); +} + +bool CPU_GPIO_PinIsBusy(GPIO_PIN Pin) +{ + return gpiod_line_is_free(pinLineStored[Pin]); +} + +bool CPU_GPIO_ReservePin(GPIO_PIN Pin, bool fReserve) +{ + pinLineStored[Pin] = gpiod_chip_get_line(_chip, Pin); + + if (pinLineStored[Pin] == NULL) + return false; + + return true; +} + +int32_t CPU_GPIO_GetPinCount() +{ + return GPIO_MAX_PIN; +} + +uint32_t CPU_GPIO_GetPinDebounce(GPIO_PIN Pin) +{ + // TODO + return 0; +} + +bool CPU_GPIO_SetPinDebounce(GPIO_PIN pinNumber, CLR_UINT64 debounceTimeMilliseconds) +{ + // TODO + return true; +} + +bool CPU_GPIO_SetDriveMode(GPIO_PIN pinNumber, GpioPinDriveMode driveMode) +{ + if (CPU_GPIO_DriveModeSupported(pinNumber, driveMode)) { + pinDirStored[pinNumber] = driveMode; + + switch (driveMode) + { + case GpioPinDriveMode_Output: + gpiod_line_request_output(pinLineStored[pinNumber], + "nanoFramework", 0); + break; + case GpioPinDriveMode_Input: + gpiod_line_request_input(pinLineStored[pinNumber], + "nanoFramework"); + break; + default: + return false; + break; + } + + return true; + } + + // TODO: complete GpioPinDriveMode support + return false; +} + +bool CPU_GPIO_DriveModeSupported(GPIO_PIN pinNumber, GpioPinDriveMode driveMode) +{ + // TODO + return true; +} + +#endif diff --git a/posix/target/PAL/CPU_Gpio_Nuttx.cpp b/posix/target/PAL/CPU_Gpio_Nuttx.cpp new file mode 100644 index 00000000..12f5b4e8 --- /dev/null +++ b/posix/target/PAL/CPU_Gpio_Nuttx.cpp @@ -0,0 +1,320 @@ + +#include + +#if defined(__nuttx__) +#include +#include +#include +#include +#include +#endif + +#if defined(__nuttx__) && defined(__gpio) + +static int openGpioCharDev(GPIO_PIN Pin) +{ + // strlen /dev/gpout100 = 13 + // I think 20 is a good size + char devpath[20]; + int fd; + int ret; + + if (pinDirStored[Pin] == GpioPinDriveMode_Output) + sprintf(devpath, "/dev/gpout%d", Pin); + else + sprintf(devpath, "/dev/gpin%d", Pin); + + fd = open(devpath, O_RDWR); + + if (fd < 0) + { + int errcode = errno; + fprintf(stderr, "ERROR: Failed to open %s: %d\n", devpath, errcode); + exit(EXIT_FAILURE); + } + + return fd; +} + +static gpio_pintype_e getGpioCharDevType(int fd) +{ + enum gpio_pintype_e pintype; + int ret; + + ret = ioctl(fd, GPIOC_PINTYPE, (unsigned long)((uintptr_t)&pintype)); + +#if defined(DEBUG) + if (ret < 0) + { + int errcode = errno; + fprintf(stderr, "ERROR: Failed to read pintype %d\n", errcode); + close(fd); + exit(EXIT_FAILURE); + } +#endif + + return pintype; +} + +static bool getGpioCharDevInValue(int fd) +{ + bool invalue; + int ret; + + ret = ioctl(fd, GPIOC_READ, (unsigned long)((uintptr_t)&invalue)); + +#if defined(DEBUG) + if (ret < 0) + { + int errcode = errno; + fprintf(stderr, "ERROR: Failed to read value %d\n", errcode); + close(fd); + exit(EXIT_FAILURE); + } +#endif + + return invalue; +} + +static void setGpioCharDevOutValue(int fd, bool outvalue) +{ + int ret; + + ret = ioctl(fd, GPIOC_WRITE, (unsigned long)outvalue); + +#if defined(DEBUG) + if (ret < 0) + { + int errcode = errno; + fprintf(stderr, + "ERROR: Failed to write value %u err %d\n", + (unsigned int)outvalue, errcode); + close(fd); + exit(EXIT_FAILURE); + } +#endif +} + +bool CPU_GPIO_Initialize() +{ + // for nuttx it's not needed for now because this is handled by char dev + // TODO: Nuttx generic char device + + pinDirStored[25] = GpioPinDriveMode_Output; + pinDirStored[2] = GpioPinDriveMode_Output; + pinDirStored[3] = GpioPinDriveMode_Output; + pinDirStored[4] = GpioPinDriveMode_Output; + pinDirStored[5] = GpioPinDriveMode_Output; + + pinDirStored[6] = GpioPinDriveMode_Input; + pinDirStored[7] = GpioPinDriveMode_Input; + pinDirStored[8] = GpioPinDriveMode_Input; + pinDirStored[9] = GpioPinDriveMode_Input; + + ioctrlFdReference[25] = openGpioCharDev(25); + ioctrlFdReference[2] = openGpioCharDev(2); + ioctrlFdReference[3] = openGpioCharDev(3); + ioctrlFdReference[4] = openGpioCharDev(4); + ioctrlFdReference[5] = openGpioCharDev(5); + ioctrlFdReference[6] = openGpioCharDev(6); + ioctrlFdReference[7] = openGpioCharDev(7); + ioctrlFdReference[8] = openGpioCharDev(8); + ioctrlFdReference[9] = openGpioCharDev(9); + + return true; +} + +bool CPU_GPIO_Uninitialize() +{ + // for nuttx it's not needed for now because this is handled by char dev + // TODO: Nuttx generc char device + + return true; +} + +void CPU_GPIO_DisablePin(GPIO_PIN Pin, GpioPinDriveMode driveMode, + uint32_t alternateFunction) +{ + GLOBAL_LOCK(); + CPU_GPIO_SetDriveMode(Pin, driveMode); + + // TODO + // set PIN to alternateFunction + + GLOBAL_UNLOCK(); + + CPU_GPIO_ReservePin(Pin, false); +} + +bool CPU_GPIO_EnableOutputPin(GPIO_PIN Pin, GpioPinValue InitialState, + GpioPinDriveMode driveMode) +{ + // check not an output drive mode + if (driveMode < (int)GpioPinDriveMode_Output) + return false; + + if (CPU_GPIO_SetDriveMode(Pin, driveMode) == false) + return false; + + CPU_GPIO_SetPinState(Pin, InitialState); + + return true; +} + +bool CPU_GPIO_EnableInputPin( + GPIO_PIN pinNumber, + CLR_UINT64 debounceTimeMilliseconds, + GPIO_INTERRUPT_SERVICE_ROUTINE pin_ISR, + void *isr_Param, + GPIO_INT_EDGE intEdge, + GpioPinDriveMode driveMode) +{ + // Check Input drive mode + if (driveMode >= (int)GpioPinDriveMode_Output) + { + return false; + } + + if (pin_ISR != NULL) { + switch (intEdge) + { + case GPIO_INT_EDGE_LOW: + case GPIO_INT_LEVEL_LOW: + case GPIO_INT_EDGE_HIGH: + case GPIO_INT_LEVEL_HIGH: + case GPIO_INT_EDGE_BOTH: + // TODO: IRQ callback not implemented + return false; + break; + + default: + break; + } + } + + if (!CPU_GPIO_SetDriveMode(pinNumber, driveMode)) + { + return false; + } + + // not implemented :: debounce time + // TODO + return true; +} + +GpioPinValue CPU_GPIO_GetPinState(GPIO_PIN Pin) +{ + enum gpio_pintype_e pintype; + bool invalue; + + invalue = getGpioCharDevInValue(ioctrlFdReference[Pin]); + + return invalue == 1 ? GpioPinValue_High : GpioPinValue_Low; +} + +void CPU_GPIO_SetPinState(GPIO_PIN Pin, GpioPinValue PinState) +{ + enum gpio_pintype_e pintype; + bool invalue; + + pinLineValue[Pin] = PinState; + pintype = getGpioCharDevType(ioctrlFdReference[Pin]); + + if (pintype == GPIO_OUTPUT_PIN) + { + switch (PinState) + { + case GpioPinValue_High: + setGpioCharDevOutValue(ioctrlFdReference[Pin], true); + break; + case GpioPinValue_Low: + setGpioCharDevOutValue(ioctrlFdReference[Pin], false); + break; + default: + break; + } + } + // TODO error? +} + +void CPU_GPIO_TogglePinState(GPIO_PIN pinNumber) +{ + GpioPinValue value = CPU_GPIO_GetPinState(pinNumber); + CPU_GPIO_SetPinState(pinNumber, (uint32_t)!value); +} + +bool IsValidGpioPin(GPIO_PIN pinNumber) +{ + return (pinNumber <= GPIO_MAX_PIN); +} + +bool CPU_GPIO_PinIsBusy(GPIO_PIN Pin) +{ + // TODO + return IsValidGpioPin(Pin); +} + +bool CPU_GPIO_ReservePin(GPIO_PIN Pin, bool fReserve) +{ + // TODO + return true; +} + +int32_t CPU_GPIO_GetPinCount() +{ + return GPIO_MAX_PIN; +} + +uint32_t CPU_GPIO_GetPinDebounce(GPIO_PIN Pin) +{ + // TODO + return 0; +} + +bool CPU_GPIO_SetPinDebounce(GPIO_PIN pinNumber, CLR_UINT64 debounceTimeMilliseconds) +{ + // TODO + return true; +} + +bool CPU_GPIO_SetDriveMode(GPIO_PIN pinNumber, GpioPinDriveMode driveMode) +{ + if (CPU_GPIO_DriveModeSupported(pinNumber, driveMode)) { + pinDirStored[pinNumber] = driveMode; + return true; + } + + // TODO + // this appears to be not possible today on Nuttx, it's predefined on driver + return false; +} + +bool CPU_GPIO_DriveModeSupported(GPIO_PIN pinNumber, GpioPinDriveMode driveMode) +{ + enum gpio_pintype_e pintype; + + pintype = getGpioCharDevType(ioctrlFdReference[pinNumber]); + + switch (pintype) + { + case GPIO_INPUT_PIN: + return driveMode == GpioPinDriveMode_Input; + break; + case GPIO_INPUT_PIN_PULLUP: + return driveMode == GpioPinDriveMode_InputPullUp; + break; + case GPIO_INPUT_PIN_PULLDOWN: + return driveMode == GpioPinDriveMode_InputPullDown; + break; + case GPIO_OUTPUT_PIN: + case GPIO_OUTPUT_PIN_OPENDRAIN: + return driveMode == GpioPinDriveMode_Output; + break; + default: + break; + } + + return false; +} + +#endif diff --git a/posix/target/PAL/CPU_Gpio_weak.cpp b/posix/target/PAL/CPU_Gpio_weak.cpp new file mode 100644 index 00000000..91ebd4f7 --- /dev/null +++ b/posix/target/PAL/CPU_Gpio_weak.cpp @@ -0,0 +1,84 @@ + +#include + +__nfweak bool CPU_GPIO_Initialize() +{ + return false; +} + +__nfweak bool CPU_GPIO_Uninitialize() +{ + return false; +} + +__nfweak void CPU_GPIO_DisablePin(GPIO_PIN Pin, GpioPinDriveMode driveMode, + uint32_t alternateFunction) +{} + +__nfweak bool CPU_GPIO_EnableOutputPin(GPIO_PIN Pin, GpioPinValue InitialState, + GpioPinDriveMode driveMode) +{ + return false; +} + +__nfweak bool CPU_GPIO_EnableInputPin( + GPIO_PIN pinNumber, + CLR_UINT64 debounceTimeMilliseconds, + GPIO_INTERRUPT_SERVICE_ROUTINE pin_ISR, + void *isr_Param, + GPIO_INT_EDGE intEdge, + GpioPinDriveMode driveMode) +{ + return false; +} + +__nfweak GpioPinValue CPU_GPIO_GetPinState(GPIO_PIN Pin) +{ + return GpioPinValue_Low; +} + +__nfweak void CPU_GPIO_SetPinState(GPIO_PIN Pin, GpioPinValue PinState) +{} + +__nfweak void CPU_GPIO_TogglePinState(GPIO_PIN pinNumber) +{} + +__nfweak bool IsValidGpioPin(GPIO_PIN pinNumber) +{ + return false; +} + +__nfweak bool CPU_GPIO_PinIsBusy(GPIO_PIN Pin) +{ + return false; +} + +__nfweak bool CPU_GPIO_ReservePin(GPIO_PIN Pin, bool fReserve) +{ + return false; +} + +__nfweak int32_t CPU_GPIO_GetPinCount() +{ + return 0; +} + +__nfweak uint32_t CPU_GPIO_GetPinDebounce(GPIO_PIN Pin) +{ + return 0; +} + +__nfweak bool CPU_GPIO_SetPinDebounce(GPIO_PIN pinNumber, CLR_UINT64 debounceTimeMilliseconds) +{ + return false; +} + +__nfweak bool CPU_GPIO_SetDriveMode(GPIO_PIN pinNumber, GpioPinDriveMode driveMode) +{ + return false; +} + +__nfweak bool CPU_GPIO_DriveModeSupported(GPIO_PIN pinNumber, GpioPinDriveMode driveMode) +{ + return false; +} diff --git a/posix/target/PAL/ConfigHelper_stubs.cpp b/posix/target/PAL/ConfigHelper_stubs.cpp new file mode 100644 index 00000000..55ffca03 --- /dev/null +++ b/posix/target/PAL/ConfigHelper_stubs.cpp @@ -0,0 +1,78 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "include/stdafx.h" + +//--// + +// bool HAL_CONFIG_BLOCK::IsGoodBlock() const +//{ +// return TRUE; +//} +// +// bool HAL_CONFIG_BLOCK::IsGoodData() const +//{ +// return TRUE; +//} +// +// bool HAL_CONFIG_BLOCK::IsGood() const +//{ +// return TRUE; +//} +// +// const HAL_CONFIG_BLOCK* HAL_CONFIG_BLOCK::Next() const +//{ +// return NULL; +//} +// +// const void* HAL_CONFIG_BLOCK::Data() const +//{ +// return NULL; +//} +// +////--// +// +// bool HAL_CONFIG_BLOCK::Prepare( const char* Name, void* Data, unsigned int Size ) +//{ +// return TRUE; +//} +// +////--// +// +// const HAL_CONFIG_BLOCK* HAL_CONFIG_BLOCK::Find( const char* Name, bool fSkipCurrent, bool fAppend ) const +//{ +// return NULL; +//} +// +////--// +// +// bool HAL_CONFIG_BLOCK::GetConfigSectorAddress(HAL_CONFIG_BLOCK_STORAGE_DATA& blData) +//{ +// return FALSE; +//} +// +// bool HAL_CONFIG_BLOCK::CompactBlock(HAL_CONFIG_BLOCK_STORAGE_DATA& blData, const ConfigurationSector* cfgStatic, +// const HAL_CONFIG_BLOCK* cfgEnd) +//{ +// return FALSE; +//} +// +// +// bool HAL_CONFIG_BLOCK::UpdateBlock( const HAL_CONFIG_BLOCK_STORAGE_DATA &blData, const void* pAddress, const +// HAL_CONFIG_BLOCK *Header, void* Data, size_t Length, const void* LastConfigAddress, bool isChipRO ) +//{ +// return FALSE; +//} +// +// bool HAL_CONFIG_BLOCK::UpdateBlockWithName( const char* Name, void* Data, size_t Length, bool isChipRO ) +//{ +// return FALSE; +//} +// + +bool GetHalSystemInfo(HalSystemInfo &systemInfo) +{ + return FALSE; +} diff --git a/posix/target/PAL/Target_BlockStorage.cpp b/posix/target/PAL/Target_BlockStorage.cpp new file mode 100644 index 00000000..c540154d --- /dev/null +++ b/posix/target/PAL/Target_BlockStorage.cpp @@ -0,0 +1,414 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "include/stdafx.h" + +///////////////////////////////////////////////////// +// DeviceBlockInfo stubs + +__nfweak SectorAddress DeviceBlockInfo_PhysicalToSectorAddress( + DeviceBlockInfo *blockInfo, + const BlockRegionInfo *pRegion, + ByteAddress phyAddress) +{ + return phyAddress; +} + +__nfweak bool DeviceBlockInfo_FindRegionFromAddress( + DeviceBlockInfo *blockInfo, + ByteAddress address, + unsigned int *blockRegionIndex, + unsigned int *blockRangeIndex) +{ + return false; +} + +__nfweak bool DeviceBlockInfo_FindNextUsageBlock( + DeviceBlockInfo *blockInfo, + unsigned int blockUsage, + unsigned int *address, + unsigned int *blockRegionIndex, + unsigned int *blockRangeIndex) +{ + return false; +} + +__nfweak bool DeviceBlockInfo_FindForBlockUsage( + DeviceBlockInfo *blockInfo, + unsigned int blockUsage, + unsigned int *address, + unsigned int *blockRegionIndex, + unsigned int *blockRangeIndex) +{ + return false; +} + +///////////////////////////////////////////////////// +// BlockStorageStream stubs + +__nfweak bool BlockStorageStream_IsXIP(BlockStorageStream *stream) +{ + return false; +} + +__nfweak bool BlockStorageStream_IsReadModifyWrite(BlockStorageStream *stream) +{ + return false; +} + +__nfweak bool BlockStorageStream_SetReadModifyWrite(BlockStorageStream *stream) +{ + return false; +} + +__nfweak bool BlockStorageStream_Initialize(BlockStorageStream *stream, unsigned int blockUsage) +{ + return false; +} + +__nfweak bool BlockStorageStream_InitializeWithBlockStorageDevice( + BlockStorageStream *stream, + unsigned int blockUsage, + BlockStorageDevice *pDevice) +{ + return false; +} + +bool BlockStorageStream_NextStream(BlockStorageStream *stream) +{ + if (stream->Device == NULL || BlockStorageDevice_Prev(stream->Device) == NULL) + return false; + + const BlockRegionInfo *pRegion; + const DeviceBlockInfo *pDevInfo; // UNDONE: FIXME: = stream->Device->GetDeviceInfo(); + + BlockStorageStream orig; + + memcpy(&orig, stream, sizeof(orig)); + + do + { + bool fLastIndex = false; + + if (stream->RangeIndex == 0) + { + if (stream->RegionIndex == 0) + { + stream->Device = BlockStorageDevice_Prev(stream->Device); + + if (stream->Device == NULL || BlockStorageDevice_Prev(stream->Device) == NULL) + { + memcpy(stream, &orig, sizeof(orig)); + return false; + } + + // UNDONE: FIXME: pDevInfo = stream->Device->GetDeviceInfo(); + + stream->RegionIndex = pDevInfo->NumRegions - 1; + } + else + { + stream->RegionIndex--; + } + + fLastIndex = true; + } + else + { + stream->RangeIndex--; + } + + pRegion = &pDevInfo->Regions[stream->RegionIndex]; + + if (fLastIndex) + { + stream->RangeIndex = pRegion->NumBlockRanges - 1; + } + + } while (BlockRange_GetBlockUsage(pRegion->BlockRanges[stream->RangeIndex]) != stream->Usage); + + // if( pDevInfo->Attribute.SupportsXIP ) Flags |= c_BlockStorageStream__XIP; + // else Flags &= ~c_BlockStorageStream__XIP; + + stream->BlockLength = pRegion->BytesPerBlock; + stream->BaseAddress = pRegion->Start + pRegion->BlockRanges[stream->RangeIndex].StartBlock * stream->BlockLength; + stream->Length = BlockRange_GetBlockCount(pRegion->BlockRanges[stream->RangeIndex]) * stream->BlockLength; + stream->CurrentIndex = 0; + + return true; +} + +bool BlockStorageStream_PrevStream(BlockStorageStream *stream) +{ + if (stream->Device == NULL || BlockStorageDevice_Prev(stream->Device) == NULL) + return false; + + const BlockRegionInfo *pRegion; + const DeviceBlockInfo *pDevInfo; // UNDONE: FIXME: = this->Device->GetDeviceInfo(); + + BlockStorageStream orig; + + memcpy(&orig, stream, sizeof(orig)); + + do + { + bool fLastIndex = false; + + if (stream->RangeIndex == 0) + { + if (stream->RegionIndex == 0) + { + stream->Device = BlockStorageDevice_Prev(stream->Device); + + if (stream->Device == NULL || BlockStorageDevice_Prev(stream->Device) == NULL) + { + memcpy(stream, &orig, sizeof(orig)); + return false; + } + + // UNDONE: FIXME: pDevInfo = this->Device->GetDeviceInfo(); + + stream->RegionIndex = pDevInfo->NumRegions - 1; + } + else + { + stream->RegionIndex--; + } + + fLastIndex = true; + } + else + { + stream->RangeIndex--; + } + + pRegion = &pDevInfo->Regions[stream->RegionIndex]; + + if (fLastIndex) + { + stream->RangeIndex = pRegion->NumBlockRanges - 1; + } + + } while (BlockRange_GetBlockUsage(pRegion->BlockRanges[stream->RangeIndex]) != stream->Usage); + + // if( pDevInfo->Attribute.SupportsXIP ) Flags |= c_BlockStorageStream__XIP; + // else Flags &= ~c_BlockStorageStream__XIP; + + stream->BlockLength = pRegion->BytesPerBlock; + stream->BaseAddress = pRegion->Start + pRegion->BlockRanges[stream->RangeIndex].StartBlock * stream->BlockLength; + stream->Length = BlockRange_GetBlockCount(pRegion->BlockRanges[stream->RangeIndex]) * stream->BlockLength; + stream->CurrentIndex = 0; + + return true; +} + +bool BlockStorageStream_Seek(BlockStorageStream *stream, unsigned int offset, SeekOrigin origin) +{ + unsigned int seekIndex; + + switch (origin) + { + case BlockStorageStream_SeekBegin: + seekIndex = 0; + break; + + case BlockStorageStream_SeekCurrent: + seekIndex = stream->CurrentIndex; + break; + + case BlockStorageStream_SeekEnd: + seekIndex = stream->Length; + break; + + default: + + return false; + } + + seekIndex += offset; + + while (seekIndex >= (int32_t)stream->Length) + { + // out of region address space + return false; + } + + while (seekIndex < 0) + { + // out of region address space + return false; + } + + stream->CurrentIndex = seekIndex; + + return true; +} + +__nfweak bool BlockStorageStream_Write(BlockStorageStream *stream, unsigned char *data, unsigned int length) +{ + return false; +} + +__nfweak bool BlockStorageStream_Erase(BlockStorageStream *stream, unsigned int length) +{ + return false; +} + +__nfweak bool BlockStorageStream_ReadIntoBuffer(BlockStorageStream *stream, unsigned char *buffer, unsigned int length) +{ + return false; +} + +bool BlockStorageStream_Read(BlockStorageStream *stream, unsigned char **buffer, unsigned int length) +{ + if (stream == NULL || !buffer) + return false; + + unsigned char *pBuffer = *buffer; + bool fXIPFound = false; + + while (length > 0) + { + int readLen = length; + + if ((stream->CurrentIndex + readLen) > stream->Length) + { + readLen = stream->Length - stream->CurrentIndex; + } + + if (!fXIPFound) + { + *buffer = (unsigned char *)(BlockStorageStream_CurrentAddress(stream)); + + fXIPFound = true; + } + + length -= readLen; + pBuffer += readLen; + stream->CurrentIndex += readLen; + } + + return true; +} + +unsigned int BlockStorageStream_CurrentAddress(BlockStorageStream *stream) +{ + return stream->BaseAddress + stream->CurrentIndex; +} + +__nfweak bool BlockStorageStream_IsErased(BlockStorageStream *stream, unsigned int length) +{ + return false; +} + +///////////////////////////////////////////////////// +// BlockStorageDevice stubs + +__nfweak BlockStorageDevice *BlockStorageDevice_Next(BlockStorageDevice *device) +{ + return NULL; +} + +__nfweak BlockStorageDevice *BlockStorageDevice_Prev(BlockStorageDevice *device) +{ + return NULL; +} + +__nfweak bool BlockStorageDevice_InitializeDevice(BlockStorageDevice *device) +{ + return false; +} + +__nfweak bool BlockStorageDevice_UninitializeDevice(BlockStorageDevice *device) +{ + return false; +} + +__nfweak DeviceBlockInfo *BlockStorageDevice_GetDeviceInfo(BlockStorageDevice *device) +{ + return NULL; +} + +__nfweak bool BlockStorageDevice_Read( + BlockStorageDevice *device, + unsigned int address, + unsigned int numBytes, + unsigned char *pSectorBuff) +{ + return false; +} + +__nfweak bool BlockStorageDevice_Write( + BlockStorageDevice *device, + unsigned int address, + unsigned int numBytes, + unsigned char *pSectorBuf, + bool readModifyWrite) +{ + return false; +} + +__nfweak bool BlockStorageDevice_Memset( + BlockStorageDevice *device, + unsigned int address, + unsigned char data, + unsigned int NumBytes) +{ + return false; +} + +//__nfweak bool BlockStorageDevice_GetSectorMetadata(BlockStorageDevice* device, unsigned int sectorStart, +//SectorMetadata* pSectorMetadata); +//__nfweak bool BlockStorageDevice_SetSectorMetadata(BlockStorageDevice* device, unsigned int sectorStart, +//SectorMetadata* pSectorMetadata); + +__nfweak bool BlockStorageDevice_IsBlockErased( + BlockStorageDevice *device, + unsigned int blockStartAddress, + unsigned int blockLength) +{ + return false; +} + +__nfweak bool BlockStorageDevice_EraseBlock(BlockStorageDevice *device, unsigned int address) +{ + return false; +} + +__nfweak void BlockStorageDevice_SetPowerState(BlockStorageDevice *device, unsigned int state) +{ + return; +} + +__nfweak bool BlockStorageDevice_FindRegionFromAddress( + BlockStorageDevice *device, + unsigned int address, + unsigned int *blockRegionIndex, + unsigned int *blockRangeIndex) +{ + return false; +} + +__nfweak bool BlockStorageDevice_FindForBlockUsage( + BlockStorageDevice *device, + unsigned int blockUsage, + unsigned int *address, + unsigned int *blockRegionIndex, + unsigned int *blockRangeIndex) +{ + return false; +} + +__nfweak bool BlockStorageDevice_FindNextUsageBlock( + BlockStorageDevice *device, + unsigned int blockUsage, + unsigned int *address, + unsigned int *blockRegionIndex, + unsigned int *blockRangeIndex) +{ + return false; +} + +///////////////////////////////////////////////////// diff --git a/posix/target/PAL/Watchdog_stubs.cpp b/posix/target/PAL/Watchdog_stubs.cpp new file mode 100644 index 00000000..23064314 --- /dev/null +++ b/posix/target/PAL/Watchdog_stubs.cpp @@ -0,0 +1,16 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "include/stdafx.h" + +//--// + +void Watchdog_Init() +{ +} + +void Watchdog_Reset() +{ +} diff --git a/posix/target/PAL/blockstorageList_stubs.cpp b/posix/target/PAL/blockstorageList_stubs.cpp new file mode 100644 index 00000000..90d2a16d --- /dev/null +++ b/posix/target/PAL/blockstorageList_stubs.cpp @@ -0,0 +1,158 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "include/stdafx.h" + +//--// + +// HAL_DblLinkedList BlockStorageList::s_deviceList; +// BlockStorageDevice* BlockStorageList::s_primaryDevice = NULL; +static BlockStorageDevice *s_primaryDevice = NULL; + +//--// + +// void BlockStorageList::Initialize() +//{ +//} +// +// bool BlockStorageList::InitializeDevices() +//{ +// return TRUE; +//} +// +// bool BlockStorageList::UnInitializeDevices() +//{ +// return TRUE; +//} +// +// bool BlockStorageList::AddDevice( BlockStorageDevice* pBSD, IBlockStorageDevice* vtable, void* config, bool Init) +//{ +// return TRUE; +//} +bool BlockStorageList_AddDevice(BlockStorageDevice *pBSD, IBlockStorageDevice *vtable, void *config, bool init) +{ + s_primaryDevice = pBSD; + + // TODO what to do with vtable and config?? + return true; +} +// +// bool BlockStorageList::RemoveDevice( BlockStorageDevice* pBSD, bool UnInit) +//{ +// return TRUE; +//} + +// BlockStorageDevice* BlockStorageList::GetFirstDevice() +//{ +// return NULL; +//} +BlockStorageDevice *BlockStorageList_GetFirstDevice() +{ + return s_primaryDevice; +} + +BlockStorageDevice *BlockStorageList_GetNextDevice(BlockStorageDevice *device) +{ + return NULL; +} + +unsigned int BlockStorageList_GetNumDevices() +{ + return TARGET_BLOCKSTORAGE_COUNT; +} + +// bool BlockStorageList::FindDeviceForPhysicalAddress( BlockStorageDevice** pBSD, unsigned int PhysicalAddress, +// ByteAddress &SectAddress) +//{ +// *pBSD = NULL; +// return FALSE; +//} +bool BlockStorageList_FindDeviceForPhysicalAddress( + BlockStorageDevice **pBSD, + unsigned int physicalAddress, + ByteAddress *blockAddress) +{ + return false; +} + +// bool BlockStorageStream::Initialize(unsigned int blockUsage) +//{ +// return FALSE; +//} +// +// bool BlockStorageStream::Initialize(unsigned int usage, BlockStorageDevice* pDevice) +//{ +// return FALSE; +//} +// +// +// unsigned int BlockStorageStream::CurrentAddress() +//{ +// return 0xFFFFFFFF; +//} +// +// bool BlockStorageStream::PrevStream() +//{ +// return FALSE; +//} +// +// bool BlockStorageStream::NextStream() +//{ +// return FALSE; +//} +// +// bool BlockStorageStream::Seek( signed int offset, SeekOrigin origin ) +//{ +// return TRUE; +//} +// +// bool BlockStorageStream::Erase( unsigned int length ) +//{ +// return TRUE; +//} +// +// bool BlockStorageStream::Write( unsigned char* data , unsigned int length ) +//{ +// return TRUE; +//} +// +// bool BlockStorageStream::ReadIntoBuffer( unsigned char* pBuffer, unsigned int length ) +//{ +// return TRUE; +//} +// +// bool BlockStorageStream::Read( unsigned char** ppBuffer, unsigned int length ) +//{ +// return TRUE; +//} +// + +//--// + +// SectorAddress DeviceBlockInfo::PhysicalToSectorAddress( const BlockRegionInfo* pRegion, ByteAddress phyAddress ) +// const +//{ +// return phyAddress; +//} +// +// bool DeviceBlockInfo::FindRegionFromAddress(ByteAddress Address, unsigned int &BlockRegionIndex, unsigned int +// &BlockRangeIndex ) const +//{ +// return FALSE; +//} +// +// bool DeviceBlockInfo::FindNextUsageBlock(unsigned int BlockUsage, ByteAddress &Address, unsigned int +// &BlockRegionIndex, unsigned int &BlockRangeIndex ) const +//{ +// return FALSE; +//} +// +// bool DeviceBlockInfo::FindForBlockUsage(unsigned int BlockUsage, ByteAddress &Address, unsigned int +// &BlockRegionIndex, unsigned int &BlockRangeIndex ) const +//{ +// return FALSE; +//} + +//--// diff --git a/posix/target/PAL/time_stubs.cpp b/posix/target/PAL/time_stubs.cpp new file mode 100644 index 00000000..7825b5e5 --- /dev/null +++ b/posix/target/PAL/time_stubs.cpp @@ -0,0 +1,16 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "include/stdafx.h" + +HRESULT Time_Initialize() +{ + return CLR_E_NOTIMPL; +} + +HRESULT Time_Uninitialize() +{ + return CLR_E_NOTIMPL; +} diff --git a/posix/target/ParseOptions_Win32.cpp b/posix/target/ParseOptions_Win32.cpp new file mode 100644 index 00000000..38f7d442 --- /dev/null +++ b/posix/target/ParseOptions_Win32.cpp @@ -0,0 +1,333 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "include/stdafx.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_RT_ParseOptions::Parameter::Parameter(const char *szName, const char *szDescription) +{ + m_szName = szName; + m_szDescription = szDescription; +} + +//--// + +CLR_RT_ParseOptions::Parameter_Generic::Parameter_Generic(const char *szName, const char *szDescription) + : CLR_RT_ParseOptions::Parameter(szName, szDescription) +{ +} + +bool CLR_RT_ParseOptions::Parameter_Generic::Parse(const char *arg) +{ + m_data = arg; + + return true; +} + +//--// + +CLR_RT_ParseOptions::Parameter_String::Parameter_String( + std::string *data, + const char *szName, + const char *szDescription) + : CLR_RT_ParseOptions::Parameter(szName, szDescription) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Parameter_String::Parse(const char *arg) +{ + *m_dataPtr = arg; + + return true; +} + +//--// + +CLR_RT_ParseOptions::Parameter_Boolean::Parameter_Boolean( + bool *data, + const char *szName, + const char *szDescription) + : CLR_RT_ParseOptions::Parameter(szName, szDescription) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Parameter_Boolean::Parse(const char *arg) +{ + int num; + + // TODO: port to linux + if (!strcmp(arg, "true") || !strcmp(arg, "on")) + { + *m_dataPtr = true; + return true; + } + + if (!strcmp(arg, "false") || !strcmp(arg, "off")) + { + *m_dataPtr = false; + return true; + } + + if (sscanf(arg, "%d", &num) == 0) + { + printf("Expecting a boolean for parameter '%s': %s\n\n", m_szName, arg); + return false; + } + + *m_dataPtr = (num != 0); + return true; +} + +//--// + +CLR_RT_ParseOptions::Parameter_Integer::Parameter_Integer( + int *data, + const char *szName, + const char *szDescription) + : CLR_RT_ParseOptions::Parameter(szName, szDescription) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Parameter_Integer::Parse(const char *arg) +{ + if (sscanf(arg, "%d", m_dataPtr) == 0) + { + printf("Expecting a number for parameter '%s': %s\n\n", m_szName, arg); + return false; + } + + return true; +} + +//--// + +CLR_RT_ParseOptions::Parameter_Float::Parameter_Float(float *data, const char *szName, const char *szDescription) + : CLR_RT_ParseOptions::Parameter(szName, szDescription) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Parameter_Float::Parse(const char *arg) +{ + if (sscanf(arg, "%f", m_dataPtr) == 0) + { + printf("Expecting a number for parameter '%s': %s\n\n", m_szName, arg); + return false; + } + + return true; +} + +//--// + +CLR_RT_ParseOptions::Command::Command(const char *szName, const char *szDescription) +{ + m_szName = szName; + m_szDescription = szDescription; +} + +bool CLR_RT_ParseOptions::Command::Parse(CLR_RT_StringVector &argv, size_t &pos, CLR_RT_ParseOptions &options) +{ + size_t argc = argv.size(); + + for (ParameterListIter it = m_params.begin(); it != m_params.end(); it++) + { + Parameter *param = *it; + + if (pos >= argc) + { + if (options.m_commands.size() > 1) + { + printf("Missing parameter for option '%s': %s\n\n", m_szName, + param->m_szName); + } + else + { + printf("Missing parameter for option '%s'\n\n", param->m_szName); + } + + return false; + } + else + { + if (param->Parse(argv[pos++].c_str()) == false) + { + return false; + } + } + } + + return true; +} + +HRESULT CLR_RT_ParseOptions::Command::Execute() +{ + NANOCLR_HEADER(); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +//--// + +CLR_RT_ParseOptions::Command_SetFlag::Command_SetFlag(bool *data, const char *szName, const char *szDescription) + : CLR_RT_ParseOptions::Command(szName, szDescription) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Command_SetFlag::Parse(CLR_RT_StringVector &argv, size_t &pos, CLR_RT_ParseOptions &options) +{ + *m_dataPtr = true; + return true; +} + +//--// + +CLR_RT_ParseOptions::CLR_RT_ParseOptions() +{ + m_fVerbose = true; +} + +HRESULT CLR_RT_ParseOptions::ExtractOptionsFromFile(const char *szFileName) +{ + NANOCLR_HEADER(); + + CLR_RT_StringVector vec; + + NANOCLR_CHECK_HRESULT(CLR_RT_FileStore::ExtractTokensFromFile(szFileName, vec)); + + NANOCLR_CHECK_HRESULT(ProcessOptions(vec)); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ParseOptions::ReprocessOptions() +{ + NANOCLR_HEADER(); + + if (CommandLineArgs.size() == 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE); + } + + NANOCLR_SET_AND_LEAVE(ProcessOptions(CommandLineArgs)); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ParseOptions::ProcessOptions(CLR_RT_StringVector &argv) +{ + // TODO: port to linux + NANOCLR_HEADER(); + + if (CommandLineArgs.size() == 0) + { + CommandLineArgs = CLR_RT_StringVector(argv); + } + + size_t argc = argv.size(); + + for (size_t i = 0; i < argc;) + { + CommandListIter it; + const char *arg = argv[i].c_str(); + + for (it = m_commands.begin(); it != m_commands.end(); it++) + { + Command *cmd = *it; + + if (!strcmp(arg, cmd->m_szName)) + { + if (m_fVerbose) + { + size_t len = cmd->m_params.size(); + size_t pos = i; + + while (len-- > 0 && pos < argc) { + auto argus = argv[++pos].c_str(); +#if defined(DEBUG) + printf("%s\n", argus); +#endif + } + } + + i++; + + if (cmd->Parse(argv, i, *this) == false) + { + Usage(); + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + NANOCLR_CHECK_HRESULT(cmd->Execute()); + break; + } + } + + if (it == m_commands.end()) + { + printf("Unknown option '%s'\n\n", arg); + + Usage(); + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_ParseOptions::Usage() +{ + CommandListIter it; + ParameterListIter it2; + size_t maxCmdLen = 0; + + for (it = m_commands.begin(); it != m_commands.end(); it++) + { + Command *cmd = *it; + std::string option = cmd->m_szName; + size_t cmdLen = strlen(cmd->m_szName); + size_t maxLen = 0; + + printf(" %s\n", cmd->m_szDescription); + + for (it2 = cmd->m_params.begin(); it2 != cmd->m_params.end(); it2++) + { + Parameter *param = *it2; + size_t len = strlen(param->m_szName); + + option += " "; + option += param->m_szName; + + if (maxLen < len) + maxLen = len; + } + + if (m_commands.size() > 1) + { + printf(" %s\n", option.c_str()); + } + + for (it2 = cmd->m_params.begin(); it2 != cmd->m_params.end(); it2++) + { + Parameter *param = *it2; + + printf(" %s = %s\n", param->m_szName, param->m_szDescription); + } + printf("\n"); + } +} + +void CLR_RT_ParseOptions::PushArguments(int argc, char *argv[], CLR_RT_StringVector &vec) +{ + for (int i = 0; i < argc; i++) + { + vec.push_back(argv[i]); + } +} diff --git a/posix/target/Various.cpp b/posix/target/Various.cpp new file mode 100644 index 00000000..8ccb238b --- /dev/null +++ b/posix/target/Various.cpp @@ -0,0 +1,542 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "include/stdafx.h" + +#include "platform_selector.h" +#include "utils.h" +#include + +//--// + +// TODO: port to linux + +// using namespace System; +// using namespace System::Diagnostics; +// using namespace Microsoft::SPOT::Emulator; + +bool HAL_Windows_IsShutdownPending() +{ + return false; // return EmulatorNative::GetEmulatorNative()->IsShuttingDown(); +} + +void HAL_Windows_AcquireGlobalLock() +{ + // UNDONE: FIXME: EmulatorNative::GetEmulatorNative()->DisableInterrupts(); +} + +void HAL_Windows_ReleaseGlobalLock() +{ + // UNDONE: FIXME: EmulatorNative::GetEmulatorNative()->EnableInterrupts(); +} + +bool HAL_Windows_HasGlobalLock() +{ + return false; // UNDONE: FIXME: !EmulatorNative::GetEmulatorNative()->AreInterruptsEnabled(); +} + +uint64_t HAL_Windows_GetPerformanceTicks() +{ + return 0; // UNDONE: FIXME: return EmulatorNative::GetEmulatorNative()->GetCurrentTicks(); +} + +void HAL_Windows_Debug_Print(char *szText) +{ + std::string str = (std::string)szText; + + // clear trailing LR & CR + int pos; + if ((pos = str.find_last_of('\n')) != std::string::npos) + { + str.erase(pos); + } + if ((pos = str.find_last_of('\r')) != std::string::npos) + { + str.erase(pos); + } + + printf("%s\n", str.c_str()); +} + +// HAL_Configuration_Windows g_HAL_Configuration_Windows; + +// unsigned int LOAD_IMAGE_CalcCRC; + +// OEM_MODEL_SKU OEM_Model_SKU = { 1, 2, 3 }; + +HAL_SYSTEM_CONFIG HalSystemConfig = { + {true}, // HAL_DRIVER_CONFIG_HEADER Header; + + //--// + + // unsigned int DebuggerPorts[MAX_DEBUGGERS]; + DEBUGGER_PORT, + + DEBUG_TEXT_PORT, + 921600, + 0, // STDIO = COM2 or COM1 + + {0, 0}, // { SRAM1_MEMORY_Base, SRAM1_MEMORY_Size }, + {0, 0}, // { FLASH_MEMORY_Base, FLASH_MEMORY_Size }, +}; + +bool ConfigurationManager_GetConfigurationBlock( + void *configurationBlock, + DeviceConfigurationOption configuration, + uint32_t configurationIndex) +{ + return true; +} + +bool ConfigurationManager_StoreConfigurationBlock( + void *configurationBlock, + DeviceConfigurationOption configuration, + uint32_t configurationIndex, + uint32_t blockSize, + bool done) +{ + return true; +} + +int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen) +{ + return 0; +} + +int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen) +{ + return 0; +} + +void NFReleaseInfo::Init( + NFReleaseInfo &NFReleaseInfo, + unsigned short int major, + unsigned short int minor, + unsigned short int build, + unsigned short int revision, + const char *info, + size_t infoLen, + const char *target, + size_t targetLen, + const char *platform, + size_t platformLen) +{ + size_t len; + + NFVersion::Init(NFReleaseInfo.Version, major, minor, build, revision); + + // better set these to empty strings, in case there is nothing to fill in + NFReleaseInfo.InfoString[0] = 0; + NFReleaseInfo.TargetName[0] = 0; + NFReleaseInfo.PlatformName[0] = 0; + + // fill each one, if it was provided + if (NULL != info) + { + len = MIN(infoLen, sizeof(NFReleaseInfo.InfoString) - 1); + memcpy(NFReleaseInfo.InfoString, info, len); + NFReleaseInfo.InfoString[len] = 0; + } + + if (NULL != target) + { + len = MIN(targetLen, sizeof(NFReleaseInfo.TargetName) - 1); + memcpy(NFReleaseInfo.TargetName, target, len); + NFReleaseInfo.TargetName[len] = 0; + } + + if (NULL != platform) + { + len = MIN(platformLen, sizeof(NFReleaseInfo.PlatformName) - 1); + memcpy(NFReleaseInfo.PlatformName, platform, len); + NFReleaseInfo.PlatformName[len] = 0; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static ON_SOFT_REBOOT_HANDLER s_rebootHandlers[5] = {NULL, NULL, NULL, NULL, NULL}; + +void __cdecl HAL_AddSoftRebootHandler(ON_SOFT_REBOOT_HANDLER handler) +{ + auto arraySize = sizeof(s_rebootHandlers) / sizeof(ON_SOFT_REBOOT_HANDLER); + for (int i = 0; i < arraySize; i++) + { + if (s_rebootHandlers[i] == NULL) + { + s_rebootHandlers[i] = handler; + return; + } + else if (s_rebootHandlers[i] == handler) + { + return; + } + } +} + +bool g_fDoNotUninitializeDebuggerPort = false; + +void __cdecl nanoHAL_Initialize(void) +{ + HAL_CONTINUATION::InitializeList(); + HAL_COMPLETION::InitializeList(); + + Events_Initialize(); +} + +void __cdecl nanoHAL_Uninitialize(void) +{ + int i; + + // UNDONE: FIXME: CPU_GPIO_Uninitialize(); + auto arraySize = sizeof(s_rebootHandlers) / sizeof(ON_SOFT_REBOOT_HANDLER); + for (i = 0; i < arraySize; i++) + { + if (s_rebootHandlers[i] != NULL) + { + s_rebootHandlers[i](); + return; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//#if !defined(BUILD_RTM) +// void __cdecl HARD_Breakpoint() +//{ +// if(::IsDebuggerPresent()) +// { +// ::DebugBreak(); +// } +//} +//#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// HAL_Mutex::HAL_Mutex() +//{ +// ::InitializeCriticalSection( &m_data ); +//} +// +// HAL_Mutex::~HAL_Mutex() +//{ +// ::DeleteCriticalSection( &m_data ); +//} +// +// void HAL_Mutex::Lock() +//{ +// ::EnterCriticalSection( &m_data ); +//} +// +// void HAL_Mutex::Unlock() +//{ +// ::LeaveCriticalSection( &m_data ); +//} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CPU_ChangePowerLevel(POWER_LEVEL level) +{ + switch (level) + { + case POWER_LEVEL__MID_POWER: + break; + + case POWER_LEVEL__LOW_POWER: + break; + + case POWER_LEVEL__HIGH_POWER: + default: + break; + } +} + +void CPU_Hibernate() +{ + int64_t start = ::HAL_Time_CurrentTime(); + + while (true) + { + // wait on SYSTEM_EVENT_FLAG_DEBUGGER_ACTIVITY as well?? + unsigned int mask = ::Events_WaitForEvents( + SLEEP_LEVEL__SLEEP, + SYSTEM_EVENT_FLAG_COM_IN | SYSTEM_EVENT_HW_INTERRUPT /*| SYSTEM_EVENT_FLAG_BUTTON */, + 1000); + + if (mask) + { + break; + } + } +} + +void CPU_Shutdown() +{ + ClrExit(); +} + +void CPU_Reset() +{ + // TODO: port to linux +} + +bool CPU_IsSoftRebootSupported() +{ + return TRUE; +} + +void CPU_SetPowerMode(PowerLevel_type powerLevel) +{ + (void)powerLevel; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SecurityKey_Copy(unsigned char KeyCopy[], signed int BytesToCopy) +{ + memset(KeyCopy, 0, BytesToCopy); +} + +void SecurityKey_LowLevelCopy(unsigned char KeyCopy[], signed int BytesToCopy) +{ + memset(KeyCopy, 0, BytesToCopy); +} + +void SecurityKey_Print() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void HAL_Windows_FastSleep(signed __int64 ticks) +{ + LARGE_INTEGER frequency; + LARGE_INTEGER countStart; + LARGE_INTEGER countEnd; + + // TODO: port to linux +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma managed(push, off) + +int hal_printf(const char *format, ...) +{ + va_list arg_ptr; + + va_start(arg_ptr, format); + + int chars = hal_vprintf(format, arg_ptr); + + va_end(arg_ptr); + + return chars; +} + +int hal_vprintf(const char *format, va_list arg) +{ + return vprintf(format, arg); +} + +int hal_fprintf(COM_HANDLE stream, const char *format, ...) +{ + va_list arg_ptr; + int chars; + + va_start(arg_ptr, format); + + chars = hal_vfprintf(stream, format, arg_ptr); + + va_end(arg_ptr); + + return chars; +} + +int hal_vfprintf(COM_HANDLE stream, const char *format, va_list arg) +{ + char buffer[512]; + int chars = 0; + + chars = hal_vsnprintf(buffer, sizeof(buffer), format, arg); + + // switch(ExtractTransport(stream)) + //{ + // default: + DebuggerPort_Write(stream, buffer, chars); // skip null terminator + // break; + + // case FLASH_WRITE_TRANSPORT: + // _ASSERTE(FALSE); + //} + + return chars; +} + +int hal_snprintf(char *buffer, size_t len, const char *format, ...) +{ + va_list arg_ptr; + int chars; + + va_start(arg_ptr, format); + + chars = hal_vsnprintf(buffer, len, format, arg_ptr); + + va_end(arg_ptr); + + return chars; +} + +int hal_vsnprintf(char *buffer, size_t len, const char *format, va_list arg) +{ + // TODO: port to linux + return vsnprintf(buffer, len, format, arg); +} + +// Compares 2 ASCII strings case insensitive. Does not take locale into account. +int hal_stricmp(const char *dst, const char *src) +{ + int f = 0, l = 0; + + do + { + if (((f = (unsigned char)(*(dst++))) >= 'A') && (f <= 'Z')) + { + f -= 'A' - 'a'; + } + if (((l = (unsigned char)(*(src++))) >= 'A') && (l <= 'Z')) + { + l -= 'A' - 'a'; + } + } while (f && (f == l)); + + return (f - l); +} + +#pragma managed(pop) + +///////////////////////////////////////////////////////////////////////////// +// +// CRC 32 table for use under ZModem protocol, IEEE 802 +// G(x) = x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 +// +static const unsigned int c_CRCTable[256] = { + 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, 0x2608EDB8, + 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7, + 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, + 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, + 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, + 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, + 0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, + 0xEC7DD02D, 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, + 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07, + 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, + 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, 0xACA5C697, 0xA864DB20, 0xA527FDF9, + 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, + 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, + 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, + 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, + 0x774BB0EB, 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, + 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, 0x0315D626, + 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 0xF5EE4BB9, + 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, + 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, + 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, + 0x8CF30BAD, 0x81B02D74, 0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, + 0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, + 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, + 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, + 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, + 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09, 0x8D79E0BE, 0x803AC667, + 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, + 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4}; + +uint32_t SUPPORT_ComputeCRC(const void *rgBlock, const uint32_t nLength, const uint32_t crc) +{ + const unsigned char *ptr = (const unsigned char *)rgBlock; + int32_t lenght = nLength; + uint32_t newCrc = crc; + + while (lenght-- > 0) + { + newCrc = c_CRCTable[((newCrc >> 24) ^ (*ptr++)) & 0xFF] ^ (newCrc << 8); + } + + return newCrc; +}; + +/////////////////////////////////////////////////////////////// + +size_t CPU_GetCachableAddress(size_t address) +{ + return address; +} + +//--// + +size_t CPU_GetUncachableAddress(size_t address) +{ + return address; +} + +// CPU sleep is not currently implemented in this target +void CPU_Sleep(SLEEP_LEVEL_type level, uint64_t wakeEvents) +{ + (void)level; + (void)wakeEvents; +}; + +/////////////////////////////////////////////////////////////// + +int nanoBooter_GetTargetInfo(TargetInfo *targetInfo) +{ + return 0; +} + +/////////////////////////////////////////////////////////////// + +void WP_Message_PrepareReception_Platform() +{ + // empty on purpose, nothing to configure +} + +// TODO: port to linux +int hal_strncpy_s(char* strDst, size_t sizeInBytes, const char* strSrc, size_t count) +{ + NATIVE_PROFILE_PAL_CRT(); +//#undef strncpy + if(strDst == NULL || strSrc == NULL || sizeInBytes == 0) {_ASSERTE(FALSE); return 1;} + + if (sizeInBytes < count + 1) + { + _ASSERTE(FALSE); + strDst[0] = 0; + return 1; + } + + strDst[count] = 0; + strncpy( strDst, strSrc, count ); + return 0; + +//#define strncpy DoNotUse_*strncpy [] +} + +int hal_strcpy_s (char* strDst, size_t sizeInBytes, const char* strSrc) +{ + NATIVE_PROFILE_PAL_CRT(); +//#undef strcpy + + size_t len; + if(strDst == NULL || strSrc == NULL || sizeInBytes == 0) {_ASSERTE(FALSE); return 1;} + + len = hal_strlen_s(strSrc); + if(sizeInBytes < len + 1) {_ASSERTE(FALSE); return 1;} + + strcpy( strDst, strSrc ); + return 0; + +//#define strcpy DoNotUse_*strcpy [] +} \ No newline at end of file diff --git a/posix/target/WatchDog.cpp b/posix/target/WatchDog.cpp new file mode 100644 index 00000000..ceccc7ec --- /dev/null +++ b/posix/target/WatchDog.cpp @@ -0,0 +1,9 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "include/stdafx.h" +//--// + +// EMPTY ON PURPOSE diff --git a/posix/target/nanoHAL_Time.cpp b/posix/target/nanoHAL_Time.cpp new file mode 100644 index 00000000..222ad716 --- /dev/null +++ b/posix/target/nanoHAL_Time.cpp @@ -0,0 +1,105 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "include/stdafx.h" + +#include + +const int CummulativeDaysForMonth[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; +const int DaysInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +#define IS_LEAP_YEAR(y) (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)) +// Number of leap years until base year, not including the target year itself. +#define NUMBER_OF_LEAP_YEARS(y) ((((y - 1) / 4) - ((y - 1) / 100) + ((y - 1) / 400)) - BASE_YEAR_LEAPYEAR_ADJUST) +#define NUMBER_OF_YEARS(y) (y - BASE_YEAR) + +#define YEARS_TO_DAYS(y) ((NUMBER_OF_YEARS(y) * DAYS_IN_NORMAL_YEAR) + NUMBER_OF_LEAP_YEARS(y)) +#define MONTH_TO_DAYS(y, m) (CummulativeDaysForMonth[m - 1] + ((IS_LEAP_YEAR(y) && (m > 2)) ? 1 : 0)) +#define DAYS_IN_MONTH(y, m) (DaysInMonth[m - 1] + ((IS_LEAP_YEAR(y) && (m == 2)) ? 1 : 0)) + +#define TIMEUNIT_TO_MINUTES 600000000 +#define TIMEUNIT_TO_MILLISECONDS 10000 +#define MILLISECONDS_TO_SECONDS 1000 +#define SECONDS_TO_MINUTES 60 +#define MINUTES_TO_HOUR 60 +#define HOURS_TO_DAY 24 + +uint64_t HAL_Time_CurrentTime() +{ + return HAL_Time_SysTicksToTime(HAL_Time_CurrentSysTicks()); +}; + +/// +/// Converts a SYSTEMTIME value to HAL time value +/// +uint64_t HAL_Time_ConvertFromSystemTime(const SYSTEMTIME *systemTime) +{ + uint64_t r = + YEARS_TO_DAYS(systemTime->wYear) + MONTH_TO_DAYS(systemTime->wYear, systemTime->wMonth) + systemTime->wDay - 1; + r = (((((r * HOURS_TO_DAY) + systemTime->wHour) * MINUTES_TO_HOUR + systemTime->wMinute) * SECONDS_TO_MINUTES + + systemTime->wSecond) * + MILLISECONDS_TO_SECONDS + + systemTime->wMilliseconds) * + TIMEUNIT_TO_MILLISECONDS; + + return r; +} + +bool HAL_Time_ToSystemTime(uint64_t time, SYSTEMTIME *systemTime) +{ + uint32_t ytd = 0; + uint32_t mtd = 0; + + time /= TIMEUNIT_TO_MILLISECONDS; + systemTime->wMilliseconds = time % MILLISECONDS_TO_SECONDS; + time /= MILLISECONDS_TO_SECONDS; + systemTime->wSecond = time % SECONDS_TO_MINUTES; + time /= SECONDS_TO_MINUTES; + systemTime->wMinute = time % MINUTES_TO_HOUR; + time /= MINUTES_TO_HOUR; + systemTime->wHour = time % HOURS_TO_DAY; + time /= HOURS_TO_DAY; + + systemTime->wDayOfWeek = (time + BASE_YEAR_DAYOFWEEK_SHIFT) % 7; + systemTime->wYear = (unsigned short)(time / DAYS_IN_NORMAL_YEAR + BASE_YEAR); + ytd = YEARS_TO_DAYS(systemTime->wYear); + + if (ytd > time) + { + systemTime->wYear--; + ytd = YEARS_TO_DAYS(systemTime->wYear); + } + + time -= ytd; + + systemTime->wMonth = (unsigned short)(time / 31 + 1); + mtd = MONTH_TO_DAYS(systemTime->wYear, systemTime->wMonth + 1); + + if (time >= mtd) + { + systemTime->wMonth++; + } + + mtd = MONTH_TO_DAYS(systemTime->wYear, systemTime->wMonth); + + systemTime->wDay = (unsigned short)(time - mtd + 1); + + return true; +} + +HRESULT HAL_Time_AccDaysInMonth(signed int year, signed int month, signed int *days) +{ + *days = MONTH_TO_DAYS(year, month); + + return S_OK; +} + +HRESULT HAL_Time_DaysInMonth(signed int year, signed int month, signed int *days) +{ + *days = DAYS_IN_MONTH(year, month); + + return S_OK; +} diff --git a/posix/target/platform_heap.cpp b/posix/target/platform_heap.cpp new file mode 100644 index 00000000..51307399 --- /dev/null +++ b/posix/target/platform_heap.cpp @@ -0,0 +1,21 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#include "include/stdafx.h" + +void *platform_malloc(size_t size) +{ + return malloc(size); +} + +void platform_free(void *ptr) +{ + free(ptr); +} + +void *platform_realloc(void *ptr, size_t size) +{ + return ptr; +} diff --git a/posix/target/stdafx.cpp b/posix/target/stdafx.cpp new file mode 100644 index 00000000..8f3f8701 --- /dev/null +++ b/posix/target/stdafx.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// +// stdafx.cpp : source file that includes just the standard includes +// test.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "include/stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/posix/target/targetHAL_Time.cpp b/posix/target/targetHAL_Time.cpp new file mode 100644 index 00000000..4667ce40 --- /dev/null +++ b/posix/target/targetHAL_Time.cpp @@ -0,0 +1,75 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "include/stdafx.h" + + +void HAL_Time_Sleep_MicroSeconds(unsigned int uSec) +{ + // UNDONE: FIXME: return EmulatorNative::GetITimeDriver()->Sleep_MicroSeconds( uSec ); +} + +void HAL_Time_Sleep_MicroSeconds_InterruptEnabled(unsigned int uSec) +{ + // UNDONE: FIXME: return EmulatorNative::GetITimeDriver()->Sleep_MicroSecondsInterruptsEnabled( uSec ); +} + +uint64_t HAL_Time_CurrentSysTicks() +{ + // TODO: port to linux + struct timespec ts; + uint64_t tick = 0u; + clock_gettime(CLOCK_MONOTONIC, &ts); + + // each 100 nanoseconds one tick + tick = ((ts.tv_sec * (uint64_t)1000000000) + ts.tv_nsec) / (uint64_t)100; + return tick; +} + +// Converts CMSIS sysTicks to .NET ticks (100 nanoseconds) +uint64_t HAL_Time_SysTicksToTime(uint64_t sysTicks) +{ + // TODO: port to linux + _ASSERTE(sysTicks < 0x8000000000000000); + + return sysTicks; +} + +uint64_t HAL_Time_CurrentDateTime(bool datePartOnly) +{ + // TODO: port to linux + return 0; +} + +bool HAL_Time_TimeSpanToStringEx(const int64_t &ticks, char *&buf, size_t &len) +{ + // TODO: port to linux + return 0; +} + +bool DateTimeToString(const uint64_t &time, char *&buf, size_t &len) +{ + // TODO: port to linux + CLR_SafeSprintf(buf, len, "%4d/%02d/%02d %02d:%02d:%02d.%03d", 0, 0, 0, 0, 0, 0, 0); + + return len != 0; +} + +char *DateTimeToString(const uint64_t &time) +{ + static char rgBuffer[128]; + char *szBuffer = rgBuffer; + size_t iBuffer = sizeof(rgBuffer) / sizeof(char); + + DateTimeToString(time, szBuffer, iBuffer); + + return rgBuffer; +} + +const char *HAL_Time_CurrentDateTimeToString() +{ + return DateTimeToString(HAL_Time_CurrentDateTime(false)); +} diff --git a/posix/target/targetPAL_Events.cpp b/posix/target/targetPAL_Events.cpp new file mode 100644 index 00000000..e7c318f6 --- /dev/null +++ b/posix/target/targetPAL_Events.cpp @@ -0,0 +1,120 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "include/stdafx.h" +#include "TimerManager.h" + +static std::unique_ptr boolEventsTimer; +static bool *saveTimerCompleteFlag = 0; + +void local_Events_SetBoolTimer_Callback() +{ + NATIVE_PROFILE_PAL_EVENTS(); + + *saveTimerCompleteFlag = true; +} + +bool Events_Initialize_Platform() +{ + boolEventsTimer = NULL; + + return true; +} + +void Events_SetBoolTimer(bool *timerCompleteFlag, uint32_t millisecondsFromNow) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // we assume only 1 can be active, abort previous just in case + if (boolEventsTimer != NULL) + { + delete boolEventsTimer.release(); + } + + if (timerCompleteFlag) + { + // As only one timer running at a time we will just save it + saveTimerCompleteFlag = timerCompleteFlag; + + boolEventsTimer = + std::make_unique(millisecondsFromNow, local_Events_SetBoolTimer_Callback); + } +} + +// mutex, condition variable and flags for CLR's global events state +static std::mutex EventsMutex; +static std::condition_variable EventsConditionVar; +static uint32_t SystemEvents; + +bool Events_Initialize() +{ + std::unique_lock scopeLock(EventsMutex); + SystemEvents = 0; + return TRUE; +} + +bool Events_Uninitialize() +{ + std::unique_lock scopeLock(EventsMutex); + SystemEvents = 0; + return TRUE; +} + +void Events_Set(uint32_t Events) +{ + { + std::unique_lock scopeLock(EventsMutex); + SystemEvents |= Events; + } + EventsConditionVar.notify_all(); +} + +uint32_t Events_Get(uint32_t EventsOfInterest) +{ + std::unique_lock scopeLock(EventsMutex); + auto retVal = SystemEvents & EventsOfInterest; + SystemEvents &= ~EventsOfInterest; + return retVal; +} + +void Events_Clear(uint32_t Events) +{ + { + std::unique_lock scopeLock(EventsMutex); + SystemEvents &= ~Events; + } + EventsConditionVar.notify_all(); +} + +uint32_t Events_MaskedRead(uint32_t Events) +{ + return SystemEvents & Events; +} + +// block this thread and wake up when at least one of the requested events is set or a timeout occurs... +uint32_t Events_WaitForEvents(uint32_t powerLevel, uint32_t wakeupSystemEvents, uint32_t timeoutMilliseconds) +{ + std::unique_lock scopeLock(EventsMutex); + + bool timeout = false; + // check current condition before waiting as Condition var doesn't do that + if ((wakeupSystemEvents & SystemEvents) == 0) + { + timeout = !EventsConditionVar.wait_for(scopeLock, std::chrono::milliseconds(timeoutMilliseconds), [=]() { + return (wakeupSystemEvents & SystemEvents) != 0; + }); + } + return timeout ? 0 : SystemEvents & wakeupSystemEvents; +} + +void Events_SetCallback(set_Event_Callback pfn, void *arg) +{ + _ASSERTE(FALSE); +} + +void FreeManagedEvent(uint8_t category, uint8_t subCategory, uint16_t data1, uint32_t data2) +{ +} diff --git a/posix/target/targetPAL_Time.cpp b/posix/target/targetPAL_Time.cpp new file mode 100644 index 00000000..7b16a149 --- /dev/null +++ b/posix/target/targetPAL_Time.cpp @@ -0,0 +1,39 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#include "include/stdafx.h" +#include "TimerManager.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void TimerCallback() +{ + GLOBAL_LOCK(); + HAL_COMPLETION::DequeueAndExec(); +} + +void Time_SetCompare(uint64_t CompareValue) +{ + static std::unique_ptr pCompletionsTimer; + + // convert to milliseconds for OS timer + auto compareMs = CompareValue / (CPU_TicksPerSecond() * (uint64_t)1000); + ASSERT(compareMs < UINT32_MAX); + + if (compareMs == 0) + { + TimerCallback(); + } + else + { + pCompletionsTimer = std::make_unique(compareMs, TimerCallback); + } +} + +#ifdef __cplusplus +} +#endif diff --git a/posix/target/targetRandom.cpp b/posix/target/targetRandom.cpp new file mode 100644 index 00000000..7249ac93 --- /dev/null +++ b/posix/target/targetRandom.cpp @@ -0,0 +1,41 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#include "include/stdafx.h" +#include +#include + +void CLR_RT_Random::Initialize() +{ +} + +void CLR_RT_Random::Initialize(int seed) +{ + (void)seed; +} + +uint32_t CLR_RT_Random::Next() +{ + std::random_device randomDevice; + + return randomDevice(); +} + +double CLR_RT_Random::NextDouble() +{ + std::random_device randomDevice; + + return ((double)randomDevice()) / ((double)0xFFFFFFFF); +} + +void CLR_RT_Random::NextBytes(unsigned char *buffer, unsigned int count) +{ + std::random_device randomDevice; + + for (unsigned int i = 0; i < count; i++) + { + buffer[i] = (unsigned char)randomDevice(); + } +} diff --git a/posix/utils/TimerManager.cpp b/posix/utils/TimerManager.cpp new file mode 100644 index 00000000..5deab043 --- /dev/null +++ b/posix/utils/TimerManager.cpp @@ -0,0 +1,159 @@ +#include +#include +#include +#include "TimerManager.h" + +extern "C" void *create_pthread(void *data) +{ + TimerManager *thread_timer_manager = static_cast(data); + thread_timer_manager->run(); + return data; +} + +TimerManager::TimerManager() : + m_bRunning(false), + m_bGo(false), + m_lMinSleep(0) +{ + int mutex_creation = pthread_mutex_init(&m_tGoLock, NULL); + if(mutex_creation != 0) { + std::cerr << "Failed to create mutex" << std::endl; + return; + } + + int mutex_cond_creation = pthread_cond_init(&m_tGoLockCondition, NULL); + if(mutex_cond_creation != 0) { + std::cerr << "Failed to create condition mutex" << std::endl; + return; + } + + int thread_creation = pthread_create(&m_tTimerThread, NULL, create_pthread, this); + if(thread_creation != 0) { + std::cerr << "Failed to create thread" << std::endl; + return; + } + m_bRunning = true; +} + +TimerManager::TimerManager(long usec, void (*callback)(void)) : + m_bRunning(false), + m_bGo(false), + m_lMinSleep(0) +{ + int mutex_creation = pthread_mutex_init(&m_tGoLock, NULL); + if(mutex_creation != 0) { + std::cerr << "Failed to create mutex" << std::endl; + return; + } + + int mutex_cond_creation = pthread_cond_init(&m_tGoLockCondition, NULL); + if(mutex_cond_creation != 0) { + std::cerr << "Failed to create condition mutex" << std::endl; + return; + } + + int thread_creation = pthread_create(&m_tTimerThread, NULL, create_pthread, this); + if(thread_creation != 0) { + std::cerr << "Failed to create thread" << std::endl; + return; + } + m_bRunning = true; + + this->one_shot = true; + this->addTimer(usec, callback); + this->start(); +} + +TimerManager::~TimerManager() +{ + pthread_mutex_lock(&m_tGoLock); + m_bRunning = false; + pthread_mutex_unlock(&m_tGoLock); + void *result; + pthread_join(m_tTimerThread, &result); + pthread_detach(m_tTimerThread); + pthread_mutex_destroy(&m_tGoLock); + pthread_cond_destroy(&m_tGoLockCondition); +} + +void TimerManager::run() +{ + //pthread_mutex_lock(&m_tGoLock); + while(m_bRunning) { + + usleep(1); + + while (!m_bGo) { + pthread_cond_wait(&m_tGoLockCondition, &m_tGoLock); + } + pthread_mutex_unlock(&m_tGoLock); + if (!m_bRunning) { + break; + } + + struct timeval l_tv; + gettimeofday(&l_tv, NULL); + usleep(std::max(0l, m_lMinSleep)); + + m_lMinSleep = 0; + long l_lMin = 0; + + for(std::list::iterator it = m_cTimers.begin(); it != m_cTimers.end(); ++it) { + TimerManager::Timer l_oTimer = *it; + long timenow = (l_tv.tv_sec * 1000000 + l_tv.tv_usec); + long elapsed_time = (timenow - (l_oTimer.start)); + l_lMin = elapsed_time - l_oTimer.duration; + + if (elapsed_time >= l_oTimer.duration) { + l_lMin = l_oTimer.duration; + l_oTimer.callback(); + + if (one_shot) { + this->stop(); + return; + } + + gettimeofday(&l_tv, NULL); + it->start = (l_tv.tv_sec * 1000000) + l_tv.tv_usec; + } + m_lMinSleep = std::min(m_lMinSleep, l_lMin); + } + } +} + +void TimerManager::start() +{ + pthread_mutex_lock(&m_tGoLock); + m_bGo = true; + pthread_cond_signal(&m_tGoLockCondition); + pthread_mutex_unlock(&m_tGoLock); +} + +void TimerManager::stop() +{ + pthread_mutex_lock(&m_tGoLock); + m_bGo = false; + pthread_mutex_unlock(&m_tGoLock); +} + +TimerManager::Timer TimerManager::setUpTimer(long micro_duration, void (*callback)(void)) +{ + struct timeval l_tv; + gettimeofday(&l_tv, NULL); + Timer l_oTimer(micro_duration, callback); + l_oTimer.start = (l_tv.tv_sec * 1000000) + l_tv.tv_usec; + return l_oTimer; +} + +void TimerManager::addTimer(long usec, void (*callback)(void)) +{ + pthread_mutex_lock(&m_tGoLock); + Timer insert = setUpTimer(usec, callback); + for (std::list::iterator it = m_cTimers.begin(); it != m_cTimers.end(); ++it) { + if (*it == insert) { + return; + } + } + m_cTimers.push_back(insert); + pthread_mutex_unlock(&m_tGoLock); +} diff --git a/posix/utils/stdafx.cpp b/posix/utils/stdafx.cpp new file mode 100644 index 00000000..8f3f8701 --- /dev/null +++ b/posix/utils/stdafx.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// +// stdafx.cpp : source file that includes just the standard includes +// test.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "include/stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/posix/utils/utils.cpp b/posix/utils/utils.cpp new file mode 100644 index 00000000..7725da86 --- /dev/null +++ b/posix/utils/utils.cpp @@ -0,0 +1,18 @@ + +#include "utils.h" + +#if defined(__linux__) +/* Paste this on the file you want to debug. */ +void print_trace(void) { + char **strings; + size_t i, size; + enum Constexpr { MAX_SIZE = 1024 }; + void *array[MAX_SIZE]; + size = backtrace(array, MAX_SIZE); + strings = backtrace_symbols(array, size); + for (i = 0; i < size; i++) + printf("%s\n", strings[i]); + puts(""); + free(strings); +} +#endif