freedos-micro-python 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- freedos_micro_python/__init__.py +8 -0
- freedos_micro_python/cli.py +106 -0
- freedos_micro_python/gen_qstrdefs.py +275 -0
- freedos_micro_python/port/arch/bpstruct.h +2 -0
- freedos_micro_python/port/arch/cc.h +4 -0
- freedos_micro_python/port/arch/epstruct.h +1 -0
- freedos_micro_python/port/base64_uc386dos.c +164 -0
- freedos_micro_python/port/file_uc386dos.c +228 -0
- freedos_micro_python/port/lib/axtls/crypto/crypto.h +45 -0
- freedos_micro_python/port/lwip-arch-cc.h +46 -0
- freedos_micro_python/port/lwip_uc386dos.c +248 -0
- freedos_micro_python/port/lwipopts.h +117 -0
- freedos_micro_python/port/math_gamma.c +63 -0
- freedos_micro_python/port/modtime_uc386dos.c +60 -0
- freedos_micro_python/port/modtls_axtls_uc386dos.c +461 -0
- freedos_micro_python/port/mpconfigport.h +358 -0
- freedos_micro_python/port/mphal_uc386dos.c +103 -0
- freedos_micro_python/port/mphalport.h +11 -0
- freedos_micro_python/port/os_uc386dos.c +264 -0
- freedos_micro_python/port/path_uc386dos.c +307 -0
- freedos_micro_python/port/pktdrv_uc386dos.c +650 -0
- freedos_micro_python/port/qstrdefsport.h +2 -0
- freedos_micro_python/port/shutil_uc386dos.c +111 -0
- freedos_micro_python/port/tempfile_uc386dos.c +129 -0
- freedos_micro_python/port/time_real_uc386dos.c +77 -0
- freedos_micro_python/port/uc386_net_uc386dos.c +126 -0
- freedos_micro_python/port/urllib_parse_uc386dos.c +360 -0
- freedos_micro_python/port/urllib_uc386dos.c +29 -0
- freedos_micro_python/scripts/build.sh +641 -0
- freedos_micro_python/scripts/build_port.sh +241 -0
- freedos_micro_python/scripts/fetch.sh +238 -0
- freedos_micro_python-0.1.0.dist-info/METADATA +131 -0
- freedos_micro_python-0.1.0.dist-info/RECORD +37 -0
- freedos_micro_python-0.1.0.dist-info/WHEEL +5 -0
- freedos_micro_python-0.1.0.dist-info/entry_points.txt +2 -0
- freedos_micro_python-0.1.0.dist-info/licenses/LICENSE +25 -0
- freedos_micro_python-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
// uc386-dos MicroPython port config — ROM_LEVEL = EXTRA_FEATURES.
|
|
2
|
+
//
|
|
3
|
+
// Started life as a clone of `upstream/ports/minimal/mpconfigport.h`
|
|
4
|
+
// (MINIMUM ROM level + REPL + GC + external import). Walked up the
|
|
5
|
+
// ROM ladder slice by slice until we hit EXTRA_FEATURES wholesale,
|
|
6
|
+
// fixing each new failure as it surfaced (qstr-hash field width,
|
|
7
|
+
// X-macro qstrs for errno, IEEE-754 inf/nan via __builtin_*,
|
|
8
|
+
// static-pool placement for special-method dunders, ...). See
|
|
9
|
+
// `addons/gnu/micropython/NOTES.md` for the per-slice diary.
|
|
10
|
+
//
|
|
11
|
+
// Port-incompatible defaults explicitly turned off below.
|
|
12
|
+
|
|
13
|
+
#include <stdint.h>
|
|
14
|
+
|
|
15
|
+
// Use the setjmp/longjmp-backed NLR (non-local return) machinery.
|
|
16
|
+
// The default x86 NLR (`upstream/py/nlrx86.c`) is GCC inline asm,
|
|
17
|
+
// which uc_core / uc386 doesn't compile — `nlr_push`/`nlr_jump`
|
|
18
|
+
// would silently expand to no-ops, leaving uninitialized garbage in
|
|
19
|
+
// the nlr_buf and crashing the parser at the first exception. The
|
|
20
|
+
// setjmp path goes through uc386's libc `_setjmp`/`_longjmp`
|
|
21
|
+
// (lib/i386_dos_libc.asm), which is real i386 asm (saves 6 dwords:
|
|
22
|
+
// ebx/esi/edi/ebp/esp/eip). Pair this with the fix in
|
|
23
|
+
// `lib/include/setjmp.h` that widens jmp_buf to 24 bytes — the old
|
|
24
|
+
// 6-byte declaration would have caused setjmp to buffer-overflow.
|
|
25
|
+
#define MICROPY_NLR_SETJMP (1)
|
|
26
|
+
|
|
27
|
+
// EXTRA_FEATURES baseline. Lights up `compile()` / `eval()` /
|
|
28
|
+
// `exec()`, `input()`, `memoryview`, `MICROPY_PY_ALL_SPECIAL_METHODS`
|
|
29
|
+
// (`__add__` / `__radd__` / `__iadd__` / `__and__` / etc on class
|
|
30
|
+
// instances), `collections.deque`, math constants (pi/e/tau/inf/
|
|
31
|
+
// nan), `math.factorial`, `math.isclose`, `bytes.hex` /
|
|
32
|
+
// `bytes.fromhex`, `str.center` / `partition` / `splitlines`,
|
|
33
|
+
// `frozenset`, **f-strings**, function attribute access
|
|
34
|
+
// (`f.__name__`), `delattr`/`setattr`, REPL Emacs keys + auto-
|
|
35
|
+
// indent + Ctrl-C → KeyboardInterrupt, deque iter+subscr,
|
|
36
|
+
// bytearray slice-assign, plus dozens of smaller surface knobs.
|
|
37
|
+
#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES)
|
|
38
|
+
|
|
39
|
+
// All previously-disabled EXTRA-default flags now enabled below
|
|
40
|
+
// (STACK_CHECK / PY_UCTYPES / TIME_TIME_TIME_NS / BUILTINS_HELP /
|
|
41
|
+
// MODULE___FILE__).
|
|
42
|
+
|
|
43
|
+
// Stack-overflow guard. With a 1 MB stack (dos_emu maps STACK_BASE
|
|
44
|
+
// 0x01000000..0x01100000), an unbounded recursion or huge frame
|
|
45
|
+
// would otherwise hit unmapped memory and surface as
|
|
46
|
+
// UC_ERR_WRITE_UNMAPPED instead of a clean RuntimeError. main.c
|
|
47
|
+
// (sed-patched in build.sh) calls `mp_stack_ctrl_init()` after
|
|
48
|
+
// mp_init to capture the real stack top, then
|
|
49
|
+
// `mp_stack_set_limit(0xC0000)` to give a 256 KB safety margin
|
|
50
|
+
// (i.e., raise RecursionError when usage hits 768 KB, well below
|
|
51
|
+
// the 1 MB hard limit).
|
|
52
|
+
#define MICROPY_STACK_CHECK (1)
|
|
53
|
+
|
|
54
|
+
// `help()` builtin — uses the upstream default help text from
|
|
55
|
+
// `py/builtinhelp.c:mp_help_default_text`. With
|
|
56
|
+
// MICROPY_PY_BUILTINS_HELP_TEXT undefined, the default
|
|
57
|
+
// (`mp_help_default_text`) is used.
|
|
58
|
+
#define MICROPY_PY_BUILTINS_HELP (1)
|
|
59
|
+
|
|
60
|
+
// `__file__` attribute on imported modules. Auto-set by
|
|
61
|
+
// upstream's `do_load_from_lexer` (builtinimport.c:158) using
|
|
62
|
+
// the lexer's `source_name` qstr — which our
|
|
63
|
+
// `uc386-dos/file_uc386dos.c:mp_lexer_new_from_file` initializes
|
|
64
|
+
// from the import filename. No port-supplied helper needed.
|
|
65
|
+
#define MICROPY_MODULE___FILE__ (1)
|
|
66
|
+
// `uctypes` — binary struct access for memoryview/buffer-like
|
|
67
|
+
// objects (define a layout dict, pin it onto a buffer, read/write
|
|
68
|
+
// fields by name). build_port.sh adds extmod/moductypes.c to the
|
|
69
|
+
// source list. The module gets registered under MP_QSTR_uctypes
|
|
70
|
+
// via MP_REGISTER_EXTENSIBLE_MODULE.
|
|
71
|
+
#define MICROPY_PY_UCTYPES (1)
|
|
72
|
+
|
|
73
|
+
// `time.time()` / `time.localtime()` / `time.gmtime()` /
|
|
74
|
+
// `time.mktime()` — wired to the DOS RTC via INT 21h AH=0x2A
|
|
75
|
+
// (date) + AH=0x2C (time-of-day) in
|
|
76
|
+
// lib/i386_dos_libc.asm:_dos_get_datetime, then converted to
|
|
77
|
+
// seconds-since-epoch by upstream's shared/timeutils. The port
|
|
78
|
+
// shim lives in `uc386-dos/modtime_uc386dos.c` and is
|
|
79
|
+
// `#include`'d into extmod/modtime.c via the
|
|
80
|
+
// MICROPY_PY_TIME_INCLUDEFILE hook (provides
|
|
81
|
+
// `mp_time_time_get` + `mp_time_localtime_get`).
|
|
82
|
+
//
|
|
83
|
+
// MICROPY_TIMESTAMP_IMPL = 1 (UINT) forces `mp_timestamp_t` to
|
|
84
|
+
// be `mp_uint_t` (32-bit on i386). The default for
|
|
85
|
+
// MICROPY_EPOCH_IS_2000 is LONG_LONG, which we can't safely
|
|
86
|
+
// return from `time.time()` without longlong int support
|
|
87
|
+
// (`mp_obj_new_int_from_ll` is a stub in LONGINT_IMPL_NONE that
|
|
88
|
+
// always raises OverflowError). 32-bit unsigned seconds-since-
|
|
89
|
+
// 2000 covers through year 2136 — adequate for a DOS port.
|
|
90
|
+
//
|
|
91
|
+
// Caveat: TIME_TIME_NS gates BOTH `time.time()` AND
|
|
92
|
+
// `time.time_ns()` in upstream modtime.c. Calling
|
|
93
|
+
// `time.time_ns()` will raise `OverflowError("small int
|
|
94
|
+
// overflow")` because it routes through
|
|
95
|
+
// `mp_obj_new_int_from_ull(mp_hal_time_ns())` and the ull stub
|
|
96
|
+
// rejects everything. Lighting it up cleanly requires
|
|
97
|
+
// MICROPY_LONGINT_IMPL_LONGLONG.
|
|
98
|
+
#define MICROPY_TIMESTAMP_IMPL (1)
|
|
99
|
+
#define MICROPY_PY_TIME_TIME_TIME_NS (1)
|
|
100
|
+
#define MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME (1)
|
|
101
|
+
#define MICROPY_PY_TIME_INCLUDEFILE "uc386-dos/modtime_uc386dos.c"
|
|
102
|
+
|
|
103
|
+
// `open()` + `import xxx` (loading `xxx.py` from disk) wired through
|
|
104
|
+
// uc386's libc INT 21h file syscalls. We provide port-supplied
|
|
105
|
+
// `mp_builtin_open_obj` / `mp_import_stat` / `mp_lexer_new_from_file`
|
|
106
|
+
// in `uc386-dos/file_uc386dos.c` (no full VFS — just enough for
|
|
107
|
+
// flat .py imports and read/write file objects). MICROPY_PY_IO=1
|
|
108
|
+
// pulls in modio.c (io.IOBase, BytesIO, StringIO) and exposes
|
|
109
|
+
// `open` in the builtins table.
|
|
110
|
+
#define MICROPY_PY_IO (1)
|
|
111
|
+
|
|
112
|
+
// `sys`-module sub-features.
|
|
113
|
+
// - sys.exit: raises `SystemExit`; pyexec_friendly_repl catches
|
|
114
|
+
// it and bails out of the REPL loop, then main() returns to
|
|
115
|
+
// the libc cleanup → INT 21h AH=4Ch with the exit code.
|
|
116
|
+
// - sys.modules: dict of imported modules. `mp_init` already
|
|
117
|
+
// initializes `mp_loaded_modules_dict` via
|
|
118
|
+
// `mp_obj_dict_init(...)`; just exposing it as `sys.modules`.
|
|
119
|
+
// - sys.argv: empty list. `mp_init`'s
|
|
120
|
+
// `MICROPY_PY_SYS_PATH_ARGV_DEFAULTS` block (runtime.c:142)
|
|
121
|
+
// auto-initializes both sys.path and sys.argv when the flags
|
|
122
|
+
// are on, so no port shim needed.
|
|
123
|
+
// - sys.path: list of directories to search on import. With
|
|
124
|
+
// MICROPY_PY_SYS_PATH=1, builtinimport.c's `stat_top_level`
|
|
125
|
+
// iterates the list and our `mp_import_stat` (file_uc386dos.c)
|
|
126
|
+
// stat-checks each candidate. Initialized in mp_init with
|
|
127
|
+
// a single empty-string entry meaning "current directory".
|
|
128
|
+
// Enabling MICROPY_PY_SYS_PATH automatically enables
|
|
129
|
+
// MICROPY_PY_SYS_ATTR_DELEGATION (per modsys.c:267), which
|
|
130
|
+
// in turn requires MICROPY_MODULE_ATTR_DELEGATION (already
|
|
131
|
+
// on at our EXTRA_FEATURES ROM level per mpconfig.h:1127).
|
|
132
|
+
#define MICROPY_PY_SYS_MODULES (1)
|
|
133
|
+
#define MICROPY_PY_SYS_EXIT (1)
|
|
134
|
+
#define MICROPY_PY_SYS_PATH (1)
|
|
135
|
+
#define MICROPY_PY_SYS_ARGV (1)
|
|
136
|
+
|
|
137
|
+
// Polish: introspection knobs default to off (or EVERYTHING-only) at
|
|
138
|
+
// EXTRA_FEATURES — opt in explicitly. All live in modules we already
|
|
139
|
+
// compile (modsys.c / objrange.c) so no new sources needed.
|
|
140
|
+
//
|
|
141
|
+
// `sys.exc_info()` returns the (type, value, tb) tuple for the
|
|
142
|
+
// currently-handled exception inside an `except:` block. Useful for
|
|
143
|
+
// generic logging / propagation.
|
|
144
|
+
#define MICROPY_PY_SYS_EXC_INFO (1)
|
|
145
|
+
// `sys.tracebacklimit` lets user code cap traceback depth. Useful
|
|
146
|
+
// in DOS where stdout is precious screen real-estate.
|
|
147
|
+
#define MICROPY_PY_SYS_TRACEBACKLIMIT (1)
|
|
148
|
+
// `range(3) == range(3)` returns True (without this, ranges only
|
|
149
|
+
// compare equal by identity). Tiny, but a frequent CPython surprise.
|
|
150
|
+
#define MICROPY_PY_BUILTINS_RANGE_BINOP (1)
|
|
151
|
+
|
|
152
|
+
// errno requires:
|
|
153
|
+
// - build.sh to pre-emit the EPERM/ENOENT/... qstrs (the module's
|
|
154
|
+
// globals table uses `MP_QSTR_##e` token paste over its X-macro
|
|
155
|
+
// list, which our grep-based gen_qstrdefs.py can't see otherwise).
|
|
156
|
+
// - MICROPY_USE_INTERNAL_ERRNO=1 so MP_EPERM resolves to the
|
|
157
|
+
// upstream's hardcoded MP_##e values rather than to the system's
|
|
158
|
+
// EPERM macros from <errno.h>. uc386's libc errno.h ships only
|
|
159
|
+
// a Linux subset (no EOPNOTSUPP / EADDRINUSE / ECONN* / EHOST* /
|
|
160
|
+
// EALREADY / EINPROGRESS), so the system path leaves several
|
|
161
|
+
// MP_##e references as bare Identifiers that fail const-eval.
|
|
162
|
+
#define MICROPY_USE_INTERNAL_ERRNO (1)
|
|
163
|
+
|
|
164
|
+
// Float — uc386 lowers `double` through the x87 FPU and uc386's
|
|
165
|
+
// libc (lib/i386_dos_libc.asm) ships sin/cos/tan/asin/acos/atan/
|
|
166
|
+
// atan2/exp/log/log10/log2/expm1/pow/sqrt/floor/ceil/trunc/fmod/
|
|
167
|
+
// modf/fabs/copysign/signbit/isnan/isinf/isfinite/nan/nearbyint/
|
|
168
|
+
// ldexp/frexp/sinh/cosh/tanh/asinh/acosh/atanh/erf/erfc plus NaN
|
|
169
|
+
// stubs for tgamma/lgamma in raw 387 asm. DOUBLE rather than
|
|
170
|
+
// FLOAT so the libc's `sin`/`cos`/... unsuffixed names match what
|
|
171
|
+
// micropython calls (FLOAT_IMPL_FLOAT calls `sinf` / `cosf` /
|
|
172
|
+
// ... which we don't have).
|
|
173
|
+
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
|
|
174
|
+
#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1)
|
|
175
|
+
|
|
176
|
+
// Math edge-case fixes — defaults are 0 across all ROM levels
|
|
177
|
+
// because they cost a few extra branches. We're not size-constrained
|
|
178
|
+
// (the EXACT float formatter alone costs more), and matching CPython
|
|
179
|
+
// behavior at infinity / NaN boundaries makes test code that relies
|
|
180
|
+
// on `math.atan2(0, 0) == 0`-style assumptions actually portable.
|
|
181
|
+
// See py/modmath.c for the wrappers each flag enables.
|
|
182
|
+
#define MICROPY_PY_MATH_ATAN2_FIX_INFNAN (1)
|
|
183
|
+
#define MICROPY_PY_MATH_FMOD_FIX_INFNAN (1)
|
|
184
|
+
#define MICROPY_PY_MATH_MODF_FIX_NEGZERO (1)
|
|
185
|
+
#define MICROPY_PY_MATH_POW_FIX_NAN (1)
|
|
186
|
+
#define MICROPY_PY_MATH_GAMMA_FIX_NEGINF (1)
|
|
187
|
+
|
|
188
|
+
// Float formatter — opt into the EXACT formatter (vs the default
|
|
189
|
+
// APPROX picked when long double has the same width as double).
|
|
190
|
+
// EXACT's headline value is a parse-and-retry loop in
|
|
191
|
+
// `py/formatfloat.c:472`: format with N digits, parse the result
|
|
192
|
+
// back, compare against the original; if not equal, retry with
|
|
193
|
+
// N+1. With APPROX the loop is gated out and the formatter walks
|
|
194
|
+
// to MAX_MANTISSA_DIGITS digits unconditionally — accumulating
|
|
195
|
+
// floating-point noise in each multiplication step and producing
|
|
196
|
+
// `print(4.0)` → `3.999999999999996` and `print(1e10)` →
|
|
197
|
+
// `09999999999.99998`. EXACT picks the SHORTEST decimal that
|
|
198
|
+
// round-trips, so simple values like 4.0 / 0.1 / 1e10 get the
|
|
199
|
+
// expected literal form back. Caveat: `mp_decimal_exp` (parsenum.c)
|
|
200
|
+
// has an `assert(sizeof(mp_large_float_t) > sizeof(mp_float_t))`
|
|
201
|
+
// guarding against picking EXACT on a platform where long double
|
|
202
|
+
// isn't wider than double — which IS our case (uc386 lowers long
|
|
203
|
+
// double through the x87 FPU but stores it as 8 bytes). build.sh
|
|
204
|
+
// sed-patches that assertion out: the algorithm still works,
|
|
205
|
+
// just at the same precision as APPROX would have used; the
|
|
206
|
+
// verify-retry loop is what actually delivers the correctness.
|
|
207
|
+
#define MICROPY_FLOAT_FORMAT_IMPL (MICROPY_FLOAT_FORMAT_IMPL_EXACT)
|
|
208
|
+
|
|
209
|
+
// Long-long int support — heap-allocated `mp_obj_int_t` for
|
|
210
|
+
// values that don't fit a small int. Default is
|
|
211
|
+
// `LONGINT_IMPL_NONE`, where `mp_obj_new_int_from_ll` /
|
|
212
|
+
// `mp_obj_new_int_from_ull` are stubs that always raise
|
|
213
|
+
// `OverflowError("small int overflow")`. That makes
|
|
214
|
+
// `time.time_ns()`, large `struct.unpack` results, and other
|
|
215
|
+
// 64-bit-int paths unusable. LONGLONG enables the real
|
|
216
|
+
// implementations in `upstream/py/objint_longlong.c` (already
|
|
217
|
+
// in our source list) and pulls heap-allocated `mp_obj_int_t`
|
|
218
|
+
// instances onto the GC heap. Same surface as the upstream
|
|
219
|
+
// stm32 / esp32 ports.
|
|
220
|
+
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG)
|
|
221
|
+
|
|
222
|
+
// `time` module — `time.ticks_ms`, `time.sleep_ms`, etc. wired
|
|
223
|
+
// through INT 1Ah AH=0 BIOS tick counter (~18.2 Hz, ~55 ms/tick)
|
|
224
|
+
// in lib/i386_dos_libc.asm and uc386-dos/mphal_uc386dos.c.
|
|
225
|
+
// Default-off at our ROM_LEVEL because upstream's ROM-level
|
|
226
|
+
// numbering puts BASIC_FEATURES (20) ABOVE CORE_FEATURES (10),
|
|
227
|
+
// so `MICROPY_PY_TIME = AT_LEAST_BASIC_FEATURES` evaluates to 0.
|
|
228
|
+
#define MICROPY_PY_TIME (1)
|
|
229
|
+
|
|
230
|
+
// extmod modules: `random`, `binascii`, `hashlib` (SHA-256 only),
|
|
231
|
+
// `re`. Each is a single source file added to build_port.sh's
|
|
232
|
+
// list and registered in build.sh's moduledefs.h. random's
|
|
233
|
+
// seed-init defaults to the BIOS tick counter so `random.seed()`
|
|
234
|
+
// with no arg picks up some entropy. hashlib pulls in the SHA-256
|
|
235
|
+
// implementation from `lib/crypto-algorithms/sha256.c` via inline
|
|
236
|
+
// `#include` (no separate source-list entry needed). re uses
|
|
237
|
+
// `lib/re1.5/*.c` similarly. binascii's CRC32 path is gated on
|
|
238
|
+
// `MICROPY_PY_DEFLATE` (off) so the unzip dep doesn't pull in.
|
|
239
|
+
#define MICROPY_PY_RANDOM (1)
|
|
240
|
+
#define MICROPY_PY_RANDOM_EXTRA_FUNCS (1)
|
|
241
|
+
#define MICROPY_PY_RANDOM_SEED_INIT_FUNC (bios_ticks())
|
|
242
|
+
extern unsigned long bios_ticks(void);
|
|
243
|
+
#define MICROPY_PY_BINASCII (1)
|
|
244
|
+
// CRC32 + DEFLATE — enabled now that build_port.sh includes the
|
|
245
|
+
// uzlib sources (crc32.c, tinflate.c, lz77.c, defl_static.c,
|
|
246
|
+
// adler32.c, header.c). DEFLATE_COMPRESS adds the encoder side
|
|
247
|
+
// (defl_static.c + lz77.c) for `deflate.DeflateIO(buf, mode, ...)`
|
|
248
|
+
// in write mode.
|
|
249
|
+
#define MICROPY_PY_BINASCII_CRC32 (1)
|
|
250
|
+
#define MICROPY_PY_DEFLATE (1)
|
|
251
|
+
#define MICROPY_PY_DEFLATE_COMPRESS (1)
|
|
252
|
+
#define MICROPY_PY_HASHLIB (1)
|
|
253
|
+
#define MICROPY_PY_HASHLIB_SHA256 (1)
|
|
254
|
+
|
|
255
|
+
// MD5 + SHA1 are gated on MICROPY_SSL_AXTLS in upstream modhashlib.c.
|
|
256
|
+
// We compile the real axtls library (upstream/lib/axtls/), so the
|
|
257
|
+
// AXTLS branch of modhashlib.c picks up its native MD5/SHA1 from
|
|
258
|
+
// crypto/md5.c and crypto/sha1.c. (Earlier the port shimmed the
|
|
259
|
+
// AXTLS API onto B-Con's public-domain hashes via
|
|
260
|
+
// uc386-dos/lib/axtls/crypto/crypto.h to get hashlib without TLS;
|
|
261
|
+
// that shim is now superseded by the real axtls build, but we keep
|
|
262
|
+
// the search path priority so it would still work if disabled.)
|
|
263
|
+
#define MICROPY_PY_HASHLIB_SHA1 (1)
|
|
264
|
+
#define MICROPY_PY_HASHLIB_MD5 (1)
|
|
265
|
+
#define MICROPY_SSL_AXTLS (1)
|
|
266
|
+
|
|
267
|
+
// Real TLS via axtls. modtls_axtls.c is the MicroPython glue,
|
|
268
|
+
// upstream/lib/axtls/{ssl,crypto}/ is the library itself. axtls's
|
|
269
|
+
// I/O is wired to mp_stream_posix_read/write (extmod/axtls-include/
|
|
270
|
+
// axtls_os_port.h) so reads/writes go through the lwIP socket's
|
|
271
|
+
// stream protocol — no separate BIO wrapper needed. Cert verification
|
|
272
|
+
// is OFF (CONFIG_SSL_CERT_VERIFICATION undef in the same header), so
|
|
273
|
+
// `import ssl` accepts whatever the server presents; this matches
|
|
274
|
+
// upstream MP's posture on resource-constrained ports. Use a CA
|
|
275
|
+
// chain via load_verify_locations once the bigger ROM budget
|
|
276
|
+
// allows — for now, server-auth is the user's responsibility.
|
|
277
|
+
#define MICROPY_PY_SSL (1)
|
|
278
|
+
// MICROPY_STREAMS_POSIX_API exposes mp_stream_posix_{read,write,lseek}
|
|
279
|
+
// in py/stream.c — axtls's SOCKET_READ/SOCKET_WRITE macros (in
|
|
280
|
+
// extmod/axtls-include/axtls_os_port.h) call those to bridge axtls
|
|
281
|
+
// I/O to the underlying lwIP socket. Without this gate the symbols
|
|
282
|
+
// are #ifdef'd out and the link fails.
|
|
283
|
+
#define MICROPY_STREAMS_POSIX_API (1)
|
|
284
|
+
|
|
285
|
+
// lwIP — IPv4-only TCP/UDP/DNS stack. Phase 1 is loopback-only
|
|
286
|
+
// (no packet driver yet), so socket(AF_INET, SOCK_STREAM) can
|
|
287
|
+
// bind/listen/connect against 127.0.0.1 within a single REPL.
|
|
288
|
+
// MICROPY_PY_SOCKET turns on the BSD-style surface modlwip.c
|
|
289
|
+
// exposes; MICROPY_PY_LWIP itself just exposes the raw `lwip`
|
|
290
|
+
// module which we don't bother with separately. The hostname
|
|
291
|
+
// default is required by extmod/modnetwork.c — we don't actually
|
|
292
|
+
// build modnetwork.c (no MICROPY_PY_NETWORK), but modlwip.c
|
|
293
|
+
// references the hostname for DNS, so set it here.
|
|
294
|
+
#define MICROPY_PY_LWIP (1)
|
|
295
|
+
#define MICROPY_PY_SOCKET (1)
|
|
296
|
+
#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "uc386-dos"
|
|
297
|
+
#define MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN 16
|
|
298
|
+
|
|
299
|
+
// modlwip.c's poll_sockets() drives this hook between events. With
|
|
300
|
+
// no real OS scheduler it's how blocking calls (DNS resolution,
|
|
301
|
+
// non-blocking-with-timeout connect, the udp_recv wait loop) drive
|
|
302
|
+
// netif RX / sys_check_timeouts forward. Empty default would deadlock
|
|
303
|
+
// any blocking lwIP call — `getaddrinfo` would never see its DNS
|
|
304
|
+
// response because the netif input loop never runs.
|
|
305
|
+
extern void uc386dos_loopback_poll(void *arg);
|
|
306
|
+
extern void sys_check_timeouts(void);
|
|
307
|
+
// Plain-statements form (no `do{}while(0)`): modlwip.c's call site
|
|
308
|
+
// is `MICROPY_PY_LWIP_POLL_HOOK\n next_stmt;` with no trailing
|
|
309
|
+
// semicolon after the macro, so a `do{}while(0)` body would fall
|
|
310
|
+
// directly into the next statement and parse-error.
|
|
311
|
+
#define MICROPY_PY_LWIP_POLL_HOOK \
|
|
312
|
+
uc386dos_loopback_poll(0); \
|
|
313
|
+
sys_check_timeouts();
|
|
314
|
+
|
|
315
|
+
#define MICROPY_PY_RE (1)
|
|
316
|
+
#define MICROPY_PY_RE_SUB (1)
|
|
317
|
+
#define MICROPY_PY_RE_MATCH_GROUPS (1)
|
|
318
|
+
#define MICROPY_PY_RE_MATCH_SPAN_START_END (1)
|
|
319
|
+
#define MICROPY_PY_HEAPQ (1)
|
|
320
|
+
|
|
321
|
+
#define MICROPY_ENABLE_COMPILER (1)
|
|
322
|
+
#define MICROPY_ENABLE_GC (1)
|
|
323
|
+
#define MICROPY_HELPER_REPL (1)
|
|
324
|
+
|
|
325
|
+
// We don't run mpy-tool.py, so the frozen-module symbols
|
|
326
|
+
// (mp_frozen_mpy_content, mp_frozen_names,
|
|
327
|
+
// mp_qstr_frozen_const_pool) don't exist; the minimal port's =1
|
|
328
|
+
// setting requires them as externs.
|
|
329
|
+
#define MICROPY_MODULE_FROZEN_MPY (0)
|
|
330
|
+
#define MICROPY_ENABLE_EXTERNAL_IMPORT (1)
|
|
331
|
+
|
|
332
|
+
#define MICROPY_ALLOC_PATH_MAX (256)
|
|
333
|
+
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (16)
|
|
334
|
+
|
|
335
|
+
typedef long mp_off_t;
|
|
336
|
+
|
|
337
|
+
#define MICROPY_HW_BOARD_NAME "uc386-dos"
|
|
338
|
+
#define MICROPY_HW_MCU_NAME "i386"
|
|
339
|
+
|
|
340
|
+
// `platform` module identity. modplatform.h's MICROPY_PLATFORM_*
|
|
341
|
+
// detections fall through to the generic "MicroPython" / "" case
|
|
342
|
+
// because our build doesn't define __linux / __GLIBC__ / etc.
|
|
343
|
+
// MICROPY_PLATFORM_VERSION IS `#ifndef`-guarded though, so we can
|
|
344
|
+
// stamp the runtime identity through that one.
|
|
345
|
+
#define MICROPY_PLATFORM_VERSION "uc386-dos i386 (PMODE/W)"
|
|
346
|
+
|
|
347
|
+
// Use the same STDOUT path the minimal port uses on linux/darwin —
|
|
348
|
+
// uc386's libc turns read(STDIN)/write(STDOUT) into INT 21h DOS calls.
|
|
349
|
+
#define MICROPY_MIN_USE_STDOUT (1)
|
|
350
|
+
|
|
351
|
+
// 256 KB GC heap. Bumped from 64 KB after the first runnable port:
|
|
352
|
+
// arbitrary input echoes back but the parser/compile path hits an
|
|
353
|
+
// UC_ERR_READ_UNMAPPED — heap exhaustion during parse-tree
|
|
354
|
+
// allocation is one likely cause. dos_emu maps a much wider data
|
|
355
|
+
// region than 64 KB so the additional fixed-region heap is fine.
|
|
356
|
+
#define MICROPY_HEAP_SIZE (262144)
|
|
357
|
+
|
|
358
|
+
#define MP_STATE_PORT MP_STATE_VM
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// uc386-dos MicroPython HAL — out-of-line implementations.
|
|
2
|
+
//
|
|
3
|
+
// The minimal port's mphalport.h normally inlines mp_hal_ticks_ms()
|
|
4
|
+
// to a constant 0 because the minimal port has no realtime source.
|
|
5
|
+
// We override that with a real BIOS-tick-backed version so the
|
|
6
|
+
// `time` module can return non-trivial ticks_ms / sleep behavior.
|
|
7
|
+
//
|
|
8
|
+
// All timing is derived from INT 1Ah AH=00h (BIOS tick counter,
|
|
9
|
+
// ~18.2 Hz, ~55 ms per tick). That's the only realtime source DOS
|
|
10
|
+
// programs can portably read without programming the PIT directly,
|
|
11
|
+
// and it matches what most DOS C runtimes use under the hood.
|
|
12
|
+
|
|
13
|
+
#include "py/mpconfig.h"
|
|
14
|
+
#include "py/mphal.h"
|
|
15
|
+
|
|
16
|
+
extern unsigned long bios_ticks(void);
|
|
17
|
+
|
|
18
|
+
// Each BIOS tick is 1000 / 18.20649 ≈ 54.9254 ms. Use 55 — the ~0.13%
|
|
19
|
+
// drift is well below what user code that reaches for ticks_ms can
|
|
20
|
+
// distinguish, and matches the rounding most DJGPP/Watcom DOS time
|
|
21
|
+
// helpers do.
|
|
22
|
+
#define BIOS_TICK_MS 55U
|
|
23
|
+
|
|
24
|
+
mp_uint_t mp_hal_ticks_ms(void) {
|
|
25
|
+
return bios_ticks() * BIOS_TICK_MS;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
mp_uint_t mp_hal_ticks_us(void) {
|
|
29
|
+
// Single-tick resolution. Multiply by 1000 (giving us 55000 µs
|
|
30
|
+
// step) so callers comparing two ticks_us readings see a
|
|
31
|
+
// monotonically-non-decreasing sequence with predictable steps.
|
|
32
|
+
return bios_ticks() * (BIOS_TICK_MS * 1000U);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
mp_uint_t mp_hal_ticks_cpu(void) {
|
|
36
|
+
// No RDTSC or PIT-direct reads here; reuse the µs scale so the
|
|
37
|
+
// value is at least monotonically non-decreasing.
|
|
38
|
+
return mp_hal_ticks_us();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
void mp_hal_delay_ms(mp_uint_t ms) {
|
|
42
|
+
// Convert ms → ticks (round up), then busy-wait until the BIOS
|
|
43
|
+
// counter has advanced that many ticks. Polls in a tight loop;
|
|
44
|
+
// there's no HLT/yield equivalent we can portably issue under
|
|
45
|
+
// PMODE/W since the extender owns interrupt dispatch.
|
|
46
|
+
if (ms == 0) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
unsigned long ticks_to_wait = (ms + BIOS_TICK_MS - 1) / BIOS_TICK_MS;
|
|
50
|
+
if (ticks_to_wait == 0) {
|
|
51
|
+
ticks_to_wait = 1;
|
|
52
|
+
}
|
|
53
|
+
unsigned long start = bios_ticks();
|
|
54
|
+
while ((bios_ticks() - start) < ticks_to_wait) {
|
|
55
|
+
// poll
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
void mp_hal_delay_us(mp_uint_t us) {
|
|
60
|
+
// Sub-tick precision isn't available, so we round up to the
|
|
61
|
+
// nearest ms and reuse the ms path. Anything < 55000 µs ends up
|
|
62
|
+
// waiting one BIOS tick, anything >= 55000 µs waits the
|
|
63
|
+
// appropriate number.
|
|
64
|
+
if (us == 0) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
unsigned long ms = (us + 999U) / 1000U;
|
|
68
|
+
mp_hal_delay_ms(ms);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// `sys.stdio.poll` and `input()`-readiness checks call this. We
|
|
72
|
+
// don't have a non-blocking stdin path under PMODE/W (INT 21h
|
|
73
|
+
// AH=0Bh exists but isn't reliable inside the dos_emu harness),
|
|
74
|
+
// so return 0 (no events ready). REPL still gets stdin via the
|
|
75
|
+
// normal `mp_hal_stdin_rx_chr` path in uart_core.c.
|
|
76
|
+
uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
|
|
77
|
+
(void)poll_flags;
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// `time.time_ns()` — nanoseconds since the configured epoch.
|
|
82
|
+
// We don't have sub-second precision from the DOS RTC (INT 21h
|
|
83
|
+
// AH=0x2C reports hundredths but we drop them for simplicity),
|
|
84
|
+
// so just multiply seconds-since-epoch by 1e9. Returned as
|
|
85
|
+
// uint64 so it can carry the full epoch timestamp without
|
|
86
|
+
// overflow on 32-bit builds.
|
|
87
|
+
#include "shared/timeutils/timeutils.h"
|
|
88
|
+
|
|
89
|
+
extern void dos_get_datetime(unsigned char out[7]);
|
|
90
|
+
|
|
91
|
+
uint64_t mp_hal_time_ns(void) {
|
|
92
|
+
unsigned char raw[7];
|
|
93
|
+
dos_get_datetime(raw);
|
|
94
|
+
unsigned int year = (unsigned int)(raw[0] | (raw[1] << 8));
|
|
95
|
+
unsigned int month = raw[2];
|
|
96
|
+
unsigned int day = raw[3];
|
|
97
|
+
unsigned int hour = raw[4];
|
|
98
|
+
unsigned int minute = raw[5];
|
|
99
|
+
unsigned int second = raw[6];
|
|
100
|
+
mp_timestamp_t secs = timeutils_seconds_since_epoch(
|
|
101
|
+
year, month, day, hour, minute, second);
|
|
102
|
+
return (uint64_t)secs * 1000000000ULL;
|
|
103
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// uc386-dos MicroPython HAL header.
|
|
2
|
+
//
|
|
3
|
+
// `mp_hal_stdin_rx_chr` / `mp_hal_stdout_tx_strn` are out-of-line in
|
|
4
|
+
// `upstream/ports/minimal/uart_core.c`. The timing-related HAL
|
|
5
|
+
// functions (mp_hal_ticks_ms, mp_hal_delay_ms, etc.) are out-of-line
|
|
6
|
+
// in `uc386-dos/mphal_uc386dos.c`, so this header just defers to the
|
|
7
|
+
// `extern` declarations py/mphal.h ships when no override is present.
|
|
8
|
+
|
|
9
|
+
static inline void mp_hal_set_interrupt_char(char c) {
|
|
10
|
+
(void)c;
|
|
11
|
+
}
|