Paul Edwards
2024-01-29 20:16:15 UTC
I am looking to create a lightweight Linux
environment for Windows and/or PDOS/386.
First let me talk about the Amiga.
https://sourceforge.net/p/pdos/gitcode/ci/master/tree/pdpclib/amistart.asm
So on entry to an executable, Commodore set
d0 to the command length, and a0 to the
command buffer. As opposed to Unix style of
parameters already parsed and on the stack,
or Windows style where you may a system call.
However, Amiga executables, after the library
is linked in, effectively have another number
hardcoded - 4. This is the SysBase where the
equivalent of glibc is hanging off. And with
the number 4 hardcoded, that C library is
unchangeable.
Commodore had goals and constraints that I
don't have.
I would like to have a more flexible SysBase,
so that I can run a flavor of PDOS under the
Amiga, and then for (certain - not ones with
a hardcoded, unchangeable 4 embedded in them)
Amiga applications to be able to run under that
instead, with files being redirected to an
emulated FAT16 disk or whatever.
So what I did was "create a convention" to pass
the SysBase in d7, and then add 2 GiB to d0 as
a flag to alert to the presence of d7.
So for my (pdpclib) applications, I check if d0
is greater than or equal to 2 GiB, and if so,
subtract 2 GiB to get the original length, and
at the same time fetch d7, and use that as the
SysBase. Otherwise I hardcode the number 4 like
everyone else.
And I'm happy with that. My pdpclib-based applications
will run under standard AmigaOS, but also can
potentially run under an emulation layer on the
Atari, or under a flavor of PDOS under the Amiga.
I set up alternative structures, and the app will
use those.
Commodore may not have liked the idea of Amiga
applications running on the Atari, so may not
have been willing to have such a scheme, so
perhaps in hindsight it would have needed some
sort of "programmer consortium" to override
Commodore.
Anyway, I'm happy with my "consortium" of 1 person
who is very late to the party. So my own executables
do what I want. And that's all I really care about.
Now I'm looking to do something similar for any
ELF executables I produce.
So I want to have the OPTION of producing an ELF
executable so that it runs on standard Linux. But
for that ELF executable to also run on some other
environment such as Windows, PDOS/386 or PDOS-generic.
Wintows and PDOS/386 don't pass anything on program
entry that I am aware of (or use). PDOS-generic does -
it passes a pointer similar to SysBase (which is why
PDOS-generic was invented in an Amiga forum).
I'm happy to change what PDOS-generic passes on the
stack, so long as it is just some extra parameters
that can be done in C instead of assembler.
I'm also happy for my (pdpclib-based) ELF executables
to be written to a new standard.
So sticking with 32-bit for now, there are two types
of ELF executables:
1. Does INT 80H
2. Uses glibc
Type 1 I have (limited) support for in PDOS/386 already
(ie I have an INT 80H handler). I do not wish to support
that in PDOS-generic as it is not possible/designed to
do that.
Type 2 I wish to run under PDOS-generic the same way
as I have a lightweight (53k) "Wine" - ie switch the
glibc references over to the native C library. I assume
this is technically possible but I've never dealt with
ELF internals before. PDOS-generic (pseudo-bios) would
be run on Windows.
But in both cases, there won't be any argc/argv on the
stack (and I don't want to change that - I want to
change the ELF executables instead).
So my question is - can someone suggest some ELF startup
code design that would work on both standard Linux and
PDOS-generic (type 2) and possibly PDOS/386 (type 1 - but
this is less possible and less important).
So with type 2, there will be a return address on the
stack, and the ELF startup code could check if that is
an unreasonably large value for argc. Or it could do
that, and then go on to check the next value on the
stack. If that is the number 1, or -1, then that is an
unreasonable value for argv[0]. So this is assumed to
be a PDOS-generic environment, and the command line is
fetched from (and then parsed) the SysBase-equivalent
instead of obtained already-broken-up from the stack.
The second flavor would require a change to PDOS-generic
to call applications with a 1 or -1 as the first
parameter, and SysBase-equivalent would be the second
parameter. I could do some "forward-planning" here
(that's my question) and pass some more parameters if
that would be helpful (would it, and what would they
be?). Note that Commodore may have failed to do forward
planning too. They probably didn't have access to
alt.os.development either.
This presumably means that the command-line breakup
code will be statically-linked into every (new) ELF
executable because there is presumably no standard
glibc function to do that (Windows has getmainargs
though, so maybe there is?). That's unfortunate, but
I can live with that.
For Type 1, I could change PDOS/386 to pass the
same things on the stack as PDOS-generic. Or maybe
it would be more appropriate to set an environment
variable and the ELF executable looks for that as
an override to inspecting the stack. PDOS-generic
could potentially do that too, although not so
easily, as there is a C90 getenv() but not setenv(),
and I wish to write my pseudo-bios in C90 as much
as possible.
Any suggestions? And any larger philosophical
questions underpinning this that I don't know
how to ask? (something similar to me not knowing
about block mode devices vs character mode
devices).
Thanks. Paul.
environment for Windows and/or PDOS/386.
First let me talk about the Amiga.
https://sourceforge.net/p/pdos/gitcode/ci/master/tree/pdpclib/amistart.asm
So on entry to an executable, Commodore set
d0 to the command length, and a0 to the
command buffer. As opposed to Unix style of
parameters already parsed and on the stack,
or Windows style where you may a system call.
However, Amiga executables, after the library
is linked in, effectively have another number
hardcoded - 4. This is the SysBase where the
equivalent of glibc is hanging off. And with
the number 4 hardcoded, that C library is
unchangeable.
Commodore had goals and constraints that I
don't have.
I would like to have a more flexible SysBase,
so that I can run a flavor of PDOS under the
Amiga, and then for (certain - not ones with
a hardcoded, unchangeable 4 embedded in them)
Amiga applications to be able to run under that
instead, with files being redirected to an
emulated FAT16 disk or whatever.
So what I did was "create a convention" to pass
the SysBase in d7, and then add 2 GiB to d0 as
a flag to alert to the presence of d7.
So for my (pdpclib) applications, I check if d0
is greater than or equal to 2 GiB, and if so,
subtract 2 GiB to get the original length, and
at the same time fetch d7, and use that as the
SysBase. Otherwise I hardcode the number 4 like
everyone else.
And I'm happy with that. My pdpclib-based applications
will run under standard AmigaOS, but also can
potentially run under an emulation layer on the
Atari, or under a flavor of PDOS under the Amiga.
I set up alternative structures, and the app will
use those.
Commodore may not have liked the idea of Amiga
applications running on the Atari, so may not
have been willing to have such a scheme, so
perhaps in hindsight it would have needed some
sort of "programmer consortium" to override
Commodore.
Anyway, I'm happy with my "consortium" of 1 person
who is very late to the party. So my own executables
do what I want. And that's all I really care about.
Now I'm looking to do something similar for any
ELF executables I produce.
So I want to have the OPTION of producing an ELF
executable so that it runs on standard Linux. But
for that ELF executable to also run on some other
environment such as Windows, PDOS/386 or PDOS-generic.
Wintows and PDOS/386 don't pass anything on program
entry that I am aware of (or use). PDOS-generic does -
it passes a pointer similar to SysBase (which is why
PDOS-generic was invented in an Amiga forum).
I'm happy to change what PDOS-generic passes on the
stack, so long as it is just some extra parameters
that can be done in C instead of assembler.
I'm also happy for my (pdpclib-based) ELF executables
to be written to a new standard.
So sticking with 32-bit for now, there are two types
of ELF executables:
1. Does INT 80H
2. Uses glibc
Type 1 I have (limited) support for in PDOS/386 already
(ie I have an INT 80H handler). I do not wish to support
that in PDOS-generic as it is not possible/designed to
do that.
Type 2 I wish to run under PDOS-generic the same way
as I have a lightweight (53k) "Wine" - ie switch the
glibc references over to the native C library. I assume
this is technically possible but I've never dealt with
ELF internals before. PDOS-generic (pseudo-bios) would
be run on Windows.
But in both cases, there won't be any argc/argv on the
stack (and I don't want to change that - I want to
change the ELF executables instead).
So my question is - can someone suggest some ELF startup
code design that would work on both standard Linux and
PDOS-generic (type 2) and possibly PDOS/386 (type 1 - but
this is less possible and less important).
So with type 2, there will be a return address on the
stack, and the ELF startup code could check if that is
an unreasonably large value for argc. Or it could do
that, and then go on to check the next value on the
stack. If that is the number 1, or -1, then that is an
unreasonable value for argv[0]. So this is assumed to
be a PDOS-generic environment, and the command line is
fetched from (and then parsed) the SysBase-equivalent
instead of obtained already-broken-up from the stack.
The second flavor would require a change to PDOS-generic
to call applications with a 1 or -1 as the first
parameter, and SysBase-equivalent would be the second
parameter. I could do some "forward-planning" here
(that's my question) and pass some more parameters if
that would be helpful (would it, and what would they
be?). Note that Commodore may have failed to do forward
planning too. They probably didn't have access to
alt.os.development either.
This presumably means that the command-line breakup
code will be statically-linked into every (new) ELF
executable because there is presumably no standard
glibc function to do that (Windows has getmainargs
though, so maybe there is?). That's unfortunate, but
I can live with that.
For Type 1, I could change PDOS/386 to pass the
same things on the stack as PDOS-generic. Or maybe
it would be more appropriate to set an environment
variable and the ELF executable looks for that as
an override to inspecting the stack. PDOS-generic
could potentially do that too, although not so
easily, as there is a C90 getenv() but not setenv(),
and I wish to write my pseudo-bios in C90 as much
as possible.
Any suggestions? And any larger philosophical
questions underpinning this that I don't know
how to ask? (something similar to me not knowing
about block mode devices vs character mode
devices).
Thanks. Paul.