Granted this isn’t fun. But it’s virtual. We live in an era of exciting expandable disks!
first off start with a full disk. That’s great. In this case the host was proxmox. It doesn’t matter. You apparently have to shut down the VM to expand the disk. Other virtualizers don’t need that. But whatever.
now for the predictable fun. That recovery partition is in the way. Not sure why NTFS needs to be contiguous but here we are.
So now we are stuck. You Google how to expand NTFS drive, how to move recovery partition, how to make disk bigger!! All in vain as everyone is pushing these nifty partition mover programs that don’t run on server. Do you just nuke the partition and hope for the best?
No, we can back it up, delete it, expand our disk and recreate it!
Capture the partition
Dism /Capture-Image /ImageFile:C:\my-system-partition.wim /CaptureDir:S:\ /Name:"My system partition"
Microsoft DiskPart version 10.0.19041.3636
Copyright (C) Microsoft Corporation.
On computer: KOMPUTER
DISKPART> list disk
Disk ### Status Size Free Dyn Gpt
-------- ------------- ------- ------- --- ---
Disk 0 Online 250 GB 200 GB
DISKPART> select disk 0
Disk 0 is now the selected disk.
DISKPART> list partition
Partition ### Type Size Offset
------------- ---------------- ------- -------
Partition 1 Primary 50 MB 1024 KB
Partition 2 Primary 49 GB 51 MB
Partition 3 Recovery 522 MB 49 GB
DISKPART> select partition 3
Partition 3 is now the selected partition.
DISKPART> delete partition OVERRIDE
DiskPart successfully deleted the selected partition.
While doom scrolling on eBay I always seem to stop and look at the upgrade version of Windows 3.1. It has to be the most clearly marked “why bother upgrading” version of Windows, and at the same time the ugliest. Fitting for the season’s ugly sweater theme!
The ugliest Windows ever
It’s amazing how terrible this thing has always looked to me. As far as ‘proof’ I remember being able to fake it out by doing a ‘copy con win.com ^Z’ type thing to create a fake windows directory with win.com & kernel286.exe … I think. But back when this was a NEW! product, I had to install Windows 3.0 anyways to get the CGA driver.
Windows 3.1 in CGA
I don’t know how I used Windows with CGA either.
Speaking of impossible, back in the dark ages of Windows/286 2.1 this thing snuck out:
Microsoft Windows/286 – Italian
One day I’d love to get this Italian Windows 2.1 and frame it? I don’t know who snuck in the Buone Fest onto the box art, but I’d like to think it was subversive, as I hadn’t seen anything like that on any of the other retail Operating System packaging?
It’s been a real struggle this year from the relocation, losing just about everything that I’d tried to do, then losing my job, that brief absolute terror of being unemployed with zero callbacks trying to job hunt to now spending nearly every waking hour at work.
Alcatel – Lucent saves the day
Speaking of stress, I haven’t had to build a physical network in ages, and this was news to me that all the SFP connectors are now vendor locked. Thinking I could just buy some cheap SFP DAC cables and plug away and I was greeted with the fact that neither the Dell, nor Cisco switches would recognize them. Oddly enough, Linux/Windows didn’t care at all. I had ordered some RJ45 10 gig SFPs to run across the data centre, and found out as well that I’d ordered Cisco keyed generic ones, and yes of course they don’t work in the Fortigate firewalls, nor the Dell switches. Those needed their own special ones. Luckily for me I had been pulling out all the old SFPs from decommissioned equipment as I had figured that the single mode fiber optics may be useful if I ever need anything, and there was a couple of these Alcatel-Lucent SFP-GIG-T (1gig) modules that at least saved the day in that I could connect stuff, while waiting for the trial and error of needing 2 weeks to get the appropriate 10 gig interfaces.
Also with mentioning is that Dell switches configure in cluster groups and the 25 gig clusters have to be configured down to 10gig mode to recognize and work with 10/1gig modules.
port-group 1/1/5
mode Eth 25g-4x
!
port-group 1/1/6
mode Eth 10g-4x
For example.
Speaking of, setting up a LACP bundle on the Dell switch was a snap! Just remember your port-groups!
interface ethernet1/1/1
description "WIN-HVN-100 port 0"
no shutdown
channel-group 1 mode active
no switchport
flowcontrol receive off
There isn’t all that much to do in the individual ethernet ports, but you get the idea. Since I’m short on cables, I’ve only got the first two ports populated, but I’m aiming for 4×25 per server!
I did find that by explicitly allowing the VLANs onto the port helped a lot. And by default, the switches do LACP so there isn’t all that much to do.
And checking the LACP status is a snap as well:
hyperv-lan-core-01# show interface port-channel 1 summary
LAG Mode Status Uptime Ports
1 L2-HYBRID up 1 day 21:45:26 Eth 1/1/1 (Up)
Eth 1/1/2 (Up)
Eth 1/1/3 (Down)
Eth 1/1/4 (Down)
Needless to say, I was happy as ‘it just worked’!
AMD Epyc 9454 48-Core Processor
Speaking of which, I deployed Hyper-V 2019 Server. Shame VMware had to go get Broadcomm’ed as there won’t be any more free Hyper-V servers, but for now it’s fine.
I had meant to write more on setting up Hyper-V as doing it through PowerShell is a bit daunting at first.
First setup your load balancing network team. In this case I’m using a 4 port 25gig card:
New-NetlbfoTeam -Name "Converged Network Team" -TeamMembers "Integrated NIC 1 Port 1-1","Integrated NIC 1 Port 2-1","Integrated NIC 1 Port 3-1","Integrated NIC 1 Port 4-1" -TeamingMode lacp
The port names are 100% system dependent, but you can get the idea. And setting the LACP was surprisingly easy.
I just load everything onto the same switch as I’m old, and trust my VLANs. And the servers are 1u so they don’t exactly have a lot of NIC’s for splitting stuff out but as always do what works for you.
The next step is to add the virtual network card onto my management VLAN in this case it’s 75
From there you can now use the ‘sconfig’ and setup your management IP address, load up Windows patches, load more drivers, and manage the server using the remote RSAT tools. Be sure to enable the remote desktop, unless you really love to type.
I went ahead and installed these services to get my servers onto an existing Hyper-V cluster. I’m sure some can be removed, but YMMV as always:
And of course, don’t forget your shared storage, in this case my servers have that 4x25gig card, and a smaller custom 2×25 gig card that I used to storage A/B. Fun times!
From there I could use sconfig to join my machines to the domain, and then finally add them into the cluster, and start moving my workload over to the new servers, which is what I’ll be doing throughout the Christmas break.
Speaking of work:
A very Christmas Vacation like tree
They ordered this very Clark Griswald like Christmas tree. They had to cut it down to get the base to fit the lobby area with it reaching into the 2nd floor. It’d been so long since I’d seen something like this at work. But thats me working remotely for nearly 20 years.
Something awe inspiring about it.
real life Snoopy
Which reminds me of this Snoopy I saw on twitter. As terrible as life feels from time to time, there is a bit of hope, and fun here and there as my muse is always quick to point out when I’m feeling down.
And sometimes it’s better to just get it out, as who knows, maybe this could be useful in the future somehow.
Thanks for everyone’s ongoing support over on Patron and here. It really means the world to me.
After seeing the spotlight on twitter from WinWorld, on NetManage Chameleon, an old TCP/IP stack that supported Windows 3.0! With more details over on the forum. I was inspired to set it up myself.
I did go a bit overboard showing how to install MS-DOS & Windows 3.0 on Qemu. Maybe it’ll help someone who wants to try to use Qemu, but is too scared? Maybe I moved too quickly.
One thing I did do differently in this run, is launching the monitor and a serial port as tcp servers so I could telnet into the VM, effectively having a way to share text like a clipboard back and forth. I’m kind of surprised I hadn’t really started using Qemu in this manner much earlier.
It’s 1995 and I’ve been nearly two years in the professional workspace. OS/2 is the dominant workstation product, Netware servers rule the world, and the year of the Linux desktop is going to happen any moment now. If you weren’t running OS/2, you were probably running Windows 3.1, only very few people were using that Linux thing. What would have been the prefect OS at the time would have been NT with a competent POSIX subsystem, but since we were denied that, enter Hiroshi Oota with BSD on Windows.
It was a late night browsing yahoo auctions Japan as one does, laughing at the absurd Famicom/Super Famicom games, and I went ahead and looked for BSD CD-ROMS, where I first came across BSD on Windows. And then I’d forgotten about it and went to work on some Darwin projects.
Fast forward 3 weeks, and vic485 had bought it, had it shipped, and uploaded on archive.org. So a big super thanks to vic485 for making this all possible!
So what is it? It’s not quite BSD, its a bunch of 16bit DLL’s that broke the kernel down into subsystems, that each rely on winmem32.dll to give access to flat/32bit address space. BSD on Windows (BOW) being a hybrid 16/32bit app is originally for Windows 3.1, with the later 1.5 update for Windows 95, which includes support for long filenames. I’m not sure if it’ll run on Windows NT or OS/2, as I don’t think
So what do you get?
The key media contents are the install floppy and the CD-ROM. Yes the setup program IS only on the floppy. Hope you get that disk image. I’m unsure what the manual is like, other than of course it is in Japanese.
compiling
It’s very much a single user mode BSD like environment complete with vi/gcc/csh/perl just to name a few. I’ve been able to test job control, and building some simple programs like Hack 1.03. I found a few issues however.
I haven’t tested enough with FreeBSD 1/2 but I can verify that from my ‘Ancient Linux on Windows‘ packages, the object format is the same, which is that early era when everything was a.out, although all different the reliance on GNU GAS & LD did make the object format the same. And it was nice to compile a hello world from my Linux cross compiler, link it on BOW, and get a running executable.
The memory is weird, in that you can add hundreds of megabytes to Windows and BOW will always run exhausted. In the bow.ini file you can set the heap for each program, and I found out from some silly trial and error that the maximum heap you can effectively give is 13 megabytes. It seems that winmem32 has a single chunk of memory where all processes run out of, hence the sub 16mb ram zone. Maybe there is a way to allocate it, but I’m unsure, maybe it’s in the book. CC1 was frequently having issues, so setting it’s heap to 13M sure helped, the linker ‘ld’ of course was running out of memory as well so setting it to 8M got me linking.
Filenames, especially on Windows 3.1 are a huge problem. All the LFN TSR’s I tried to load just resulted in a full crash. I had to point the linker to the CD-ROM live filesystem, which maybe would be tedious on a real machine, but under emulation it’s fine.
BOW does NOT like Qemu. At all. It won’t under otvdm either. I suspect NT is a no go but I haven’t tried. Oddly enough it’s not a timing issue, as it does run under VMware. There is an advantage to running it under Windows 95, is that it supports long filenames. 86Box works as well, I even was using the Pentium II Xeon at 400Mhz and that ran fine.
Probably the most annoying and silly thing is that the GCC C compiler doesn’t have C++ style comments turned on. Not being able to use ‘//’ is quite annoying.
Hack 1.03 running on my PS/2 model 80
Hack ran fine on my 386, which was a pleasant surprise!. It was really cool to have Word+Excel and Hack running at the same time.
Had I known about this, it would have been an incredible bridge product. Not to mention cross compiling to even Win32, or Linux. Not to mention at the time being able to run BSD with no real pain, just install and go
simple IRC test
There is generic TCP/IP Winsock support in BOW 1.5 as it simply calls winsock. This also includes the ability to run daemons, however limitations in BOW are quickly exposed, such as missing setuid/setgid sno there is no ability to impersonate lower privileged users. MMAP stuff also doesn’t seem to work, although I was able to build a super simple port of Apache 1.3.1 to BSD on Windows (BOW).
While BOW may appear to be very BSD like, there is a lack of a the mmap Apache needs, along with user mapping & impersonation. I ended up using the EMX – OS/2 system code, since it’s very POSIX like without relying on the Unix like OS actually working.
I’ve been able to serve pages to myself, however BOW crashing out many emulators and hypervisors kind of stops me from putting it on the internet. BOW enthusiasts can download it from archive.org
Today, there is really no point to BOW, it’s an interesting oddity, but back in the day, for a jr network administrator being able to run the Unix version of the snmp tools, even if it’s only client side would have been great. If tftpd could be built to run this would have been beyond amazing, as you not only get BSD, but full Windows apps at the same time, much like MachTen.
It’s a shame I never knew this was a thing, I certainly would have been evangelizing BOW! Who knows what other treasures are in the parallel societies of Japan/Asia/Europe?
Back in the olden days of when Microsoft had pivoted out of OS/2 in a hurry, I’ve always felt that the common ‘OMF’ objects ought to link for OS/2. But for some reason I never tried. But for some reason I thought I’d try it today.
I first installed Microsoft C 6.0, and set it up for a native OS/2 to OS/2 1.2 setup. This way I get a pure OS/2 include/library directory set. In retrospect, I don’t know why I didn’t just use 2 include / library directory sets to far easier target stuff, without dealing with changing the default names, and making linking an all around living hell.
So the first thing to do is to tell QuickC for Windows to default to the OS/2 include directory (turns out it wont link anyways). Compiling is nothing special. When setting up the project you’ll need a DEF file, I use this simple one:
NAME QCO2 WINDOWAPI
PROTMODE
CODE PRELOAD
Nothing to it!
I tried to fight the Windows linker, but it figures out what you are doing and won’t do it. But can you manually link? Well QuickC for Windows does include a DOS linker, and it’s oddly enough newer than the one for Microsoft C 6.0!
C:\proj\o2>msdos \WIN16APP\QCWIN\bin\link hi.obj
Microsoft (R) Segmented-Executable Linker Version 5.15
Copyright (C) Microsoft Corp 1984-1991. All rights reserved.
Run File [hi.exe]:
List File [NUL.MAP]:
Libraries [.LIB]: doscalls SLIBCE
Definitions File [NUL.DEF]: qco2.def
C:\proj\o2>msdos hi.exe
This program cannot be run in DOS mode.
Manually invoking the linker wasn’t all too hard, just answer the 30 questions. I did set the LIB environment variable so it picked up the libraries just fine. And yes, it created my OS/2 binary no problem!
And as you saw from above, yes it does run!
I do suppose the graphical editors would have been nice some 30 years ago, but in today’s era, sadly it doesn’t matter. QuickC for Windows won’t run under WLO, so this prevents it being a backdoor GUI/Protected mode compiler for OS/2. It’s a shame too as at least running under Windows 3.0, QuickC for Windows is WAY faster than using Microsoft C 6.00 in either read mode, protected mode with smartdrive.. I’m not sure what the deal is. Even with the advanced caching SCSI controller.
A talk from Dave Probert on the design of the NTOS kernel. Shame Microsoft didn’t put this anywhere people could have found this 20+ years ago, just as a shame they never opened up NTOS like they did that even tepid Windows Research Kernel. It goes without saying this is the ‘Linux is a cancer’ generation, with the crazed idea that looking at Linux would contaminate Windows.
So I had gotten this Boca Ram/2 card with 2MB of RAM, with space for an additional 6MB. Unfortunately trying to find matching memory has been a lost cause. Since the existing memory is 9 chip modules, I take that to mean it’s parity RAM, so I went shopping for much more available 3 chip modules.
2MB!
I picked up 2x 1MB modules for £10.
Slotting them carefully into the ram card, taking great care as the clips are plastic!
4MB of ram slotted, made in the USA!
Now from what I can remember being told is to never ever ever mix memory types like this. But logically I have to think that 9×1 = 4+4+1, right? RIGHT?!
I copied the @7A7A.ADF onto the reference disk image, slotted the card and booted up to the config, and toggled the card to 4M
4M (4 SIMM modules)
I didn’t trust the auto-config, plus I just wanted to see what was there. Also I’ve always wondered if the PS/2 model 60 (or 30? 50z?) can slot higher density than the 256kb SIMM’s that IBM had used. I guess one day I’ll give it a shot.
Anyways thinking that this is about done, I save the config and reboot and now It’s Bocaram/2 issues.
Immediately, on reboot I get error 164.
164 POST detected a base memory or extended memory size mismatch error.
1. Run F1 Setup. Check System Summary menu for memory size change. 2. Run the Extended Memory Diagnostic tests.
Booting from the reference disk just crashes the PC.
Fantastic.
Pressing F1 however does let you boot, ignoring the issue.
After a bunch of digging I found this zip file with some utils. And just guessing br2pmems ‘fixes’ the CMOS settings allowing the machine to boot normally.
So now it’ll recognize the 5MB of RAM, and just boot normally. GREAT. But booting the reference disk still hangs the machine.
Which then brings me to the next upgrade:
The IBM SCSI with Cache
The IBM SCSI with Cache aka the SPOCK. Since I ruined the one SCSI card, and ended up picking up a second card, but this time with the appropriate cable I’ve caused a massive market panic on Microchannel SCSI cards. Seriously check eBay, and you will see that the pricing has collapsed with many now selling in the £20-30 range. You’re welcome!
Not really wanting a 3rd SCSI card, but my eye saw this one with the cache RAM, and I figured if I wanted the ultimate PS/2 of course I’d want a caching controller. This looks to be the first rev of the PCB, but with the ‘hot fixes’ in place from the second rev. While the ROMs are stepping back to 1990, I don’t care much about the 1GB disk limit, as the BlueSCSI can emulate all the available devices in the chain, so I’m not losing anything in the way of capacity. This is a 286 after all.
Since the RAM card screws up the setup program, I have to remove it, and the old SCSI controller, re-configure the system with all the RAM and disks removed first. Then put in the new controller, and re-run setup.
I just accept the defaults, and reboot to check what happened. So far it looks good, slot 8 being near the middle of the PCB, and closer to the disk cage where the blue SCSI rests.
placehold all the drives!
Remembering that the IBM controllers inventory the disks backwards, the 380MB disk image on SCSI ID 6, is the primary boot disk. I didn’t set it to the full 1GB as I want to later see how older versions of DOS/OS2 work with this, and I know they have issues with disks bigger than 512MB, but I figured matching a disk that did exist in 1988 would be more realistic.
With the SCSI setup, I could put the troublesome Boca board back with the RAM, and get my system booting up with the new “faster” SCSI controller, and all that new RAM.
Old SCSI controller
Of course I did a few benchmarks on the old SCSI controller so I would know how much more awesome the new one is.
As you can see this is booted with my normal config.sys with a himem.sys and smartdrv from Windows 3.1 on a MS-DOS 5.1 install.
2,345.8 KB/sec With himem.sys & smartdrv
2,347.5 KB/sec with no himem.sys
2,316.6 KB/sec with runtime xmsmmgr & smartdrv
2,334.0 KB/sec with Windows 3.1 himem.sys no smartdrv
So, with these scores in hand, you can see that the penalty for various XMS memory access being turned on is there, but it’s nowhere near as massive as I’d have thought for performance. Even with it just being there, although again it’s so minimal.
Now for the real shocker:
2,079.2 KB/Sec
That’s right, the advanced card is slower. A good 11% slower. Well, that was disappointing. I’m still keeping it in the machine, as having a hardware caching controller was all the rage, just like Mach microkernels. Maybe it’d make more of a difference in a 32bit system, but it’s performance is very underwhelming. For anyone wondering, the WDC AC2340, is an EIDE 340MB hard disk, with a 64kb cache. Im sure it was considered very fancy, and fast for the era, and it’s nice to know that no matter the SCSI controller, the BlueSCSI blows it out of the water. Also keeping in mind that MFM data transfers are usually sub 400KB/sec, so this is much more faster.
Okay you have all this XMS what are you going to do with it?
Well, after I did manage to get this original copy of Word for Windows 1.0, I thought that it would be a good test. One fun thing is that it includes the ‘runtime’ version of Windows 2.11, which can also upgrade an existing install of Windows 2 if detected. Running Windows 2 on MS-DOS 5, does involve loading the setver command in the config.sys, and rebooting. Windows 2 cannot use XMS (more on that) but instead uses the older LIM EMS standard that allows a 64kb page to be viewed from a far larger card. Since the 8086/80286 still use 64kb segments it’s not all that crazy to use.
And that brings me to this great program EMM286!
It allocates a 64kb page in low ROM, and backfills it from XMS. So I give it 3MB, and now I have 1.3MB of XMS left, and 3MB of LIM EMS ready for Windows!
So now I have EMS & XMS! And didn’t have to get some pesky EMS board either. I am pretty sure you need device drivers to use EMS, so how do you use LIM EMS under OS/2 1.x? I have no idea. Probably not I guess?
Anyways I run word, everything is great, it sees extra ram. I exit windows, and unload EMM286, and ..
3.4MB of XMS available? Somehow I lost a megabyte of RAM from Windows 2?! I’m not sure what is going on, or why or how Windows even touched it. Needless to say if you want it back, you need to reboot.
DOS 10.21494KB free!
That’s right 494KB free! I thought MS-DOS under OS/2 just used some stubs in real mode, and called back to protected mode. No doubt this is totally wrong, there has to be some weird version of DOS+OS2 that actually runs in real mode going on here. I know that ‘bimodal drivers’ were a thing, but it sure seems like there really is a ‘real mode OS/2’ kernel with MS-DOS tacked onto the side.
Windows 3.0 standard mode, 286 + 5MB of RAM
It’s annoying OS/2 can’t tell you how much ram it sees and what is in use, but at least Windows 3.0 can. It’s more than enough to run Sim City, clearly making this one of the more expensive machines to run the game as intended. With the added RAM it doesn’t thrash as hard, but having emulated disks probably doesn’t matter as much as access time is always zero, and it’ll stream data as fast as it can. You can feel the difference moving between tasks, but things like the OS/2 file manager that loads a view into every directory is still incredibly slow. What were they thinking?!
Thouhts?
Back in the day this would have been an incredibly expensive upgrade. And is it worth it? The machine is still locked at 10Mhz. The FPU is also locked at 10Mhz, and you can feel it. The lightening fast disk access, despite it being some 11% slower is really hard to tell. Does the caching help at all? Applications don’t have to page in/out like crazy before as there is enough RAM to actually run them, but that is where the 10Mhz processor just isn’t there.
Just like the caching SCSI controller, I’m sure we’ve all heard how having that magical EMS memory would help out games like Wing Commander.
XMS/DOS High + EMM286 on the left, and just XMS + DOS High on the right
Well, I had to put them side by side, as I couldn’t believe it, but adding EMS made it noticeably slower. I was *NOT* expecting that. I should add that I used Vegas & this quick tutorial, on how to pan & resize one video to get them side by side. No doubt it’s not perfect but it’s enough to see that once the ship explodes, the performance on the EMS configuration is greatly throttled. It’s moments like this that makes me wonder is this something the caching SCSI card would do better implicitly? Or is it snake oil as well?
3MB is enough to load OS/2, and one application, just as Word v1 or Excel v2/v3 load just fine, but swapping between them is basically unloading one from memory, and loading the other back out to disk. It’s a shame RAM cost so much 1987-1992 as people really could have benefited from it. It’s just utterly bizarre that on such an outrageously expensive system that you even need RAM upgrade cards, it really should have been baked into the main logic board.
I’m not sure if I covered the Windows NT 3.1 build 196 before. First the most obvious is that as of this moment it’s the earliest version of Windows NT available.
So let’s do some obligatory scratch of the surface. Like all the other 1991 pre-releases there really is just a text mode setup install script. Choosing the lesser amount of pain, I went with a MS-DOS hosted install. However, using MS-DOS 6.22 resulted in a broken dual boot system. But we live in the era of virtual machines, so it really doesn’t matter. I’m using Qemu 0.14-rc2, something that is ‘era correct’ for when the first avalanche broke on early Windows NT pre-releases. I’ve had issues with more modern versions of Qemu, and I felt that if we’re using vintage software may as well go in all the way.
The boot loader identifies itself as being 1990 vintage. Pretty sure it doesn’t mean anything, but we haven’t been blessed with the “blue screen” of ARC yet.
The login screen and desktop have a very strong Windows 3.1 beta feel to them. And that would land this where it was, Windows was such a big seller that Maritz had been trying to convince Gates & Balmer to ‘switch to the Windows horse’ in the spring/summer of 1990, culminating in Gate’s July decision to walk away from NT/OS2 and rebrand the new OS as Windows NT. Oddly enough it was Balmer who was in favour of OS/2 & IBM. (Showstopper 89-90)
At first glance the opening window isn’t all that interesting. It’s just very. Windows.
Rest assured Reversi, of course made the this Win32 cut. And it’s full of weird easter eggs, oddly enough in the OS/2 surviving bits.
type OS2LDR.DOS
OS2LDR 01.00.01
by KeithMo 01/08/91
On the Discord there had been a big discussion about early NT executable formats, and the whole COFF vs ECOFF vs PE/PEI. I had tried to hunt down the specific version of GCC I used ages to to build a so called Dec Alpha GCC cross compiler, but the short version is that it didn’t work as we don’t have any assembler/linker for anything GNU targets. There had been a cygwin port andanOpenNT on Alpha, but all that is lost to the winds, minus what few scraps I had saved. I did try building some cross tools to elf hoping to just objcopy out the data and get linkable objects, but that didn’t work either.
So I though this was a perfect opportunity to take a look at this early pre-release version of NT, and although I do know that you have to convert your objects into something the ‘COFF’ linker will accept:
And I never really paid that much attention to the object files. I do know that you can link them with Link386 for OS/2, but the NT object files themselves report:
wsl file SIMPLE.OBJ
SIMPLE.OBJ: Intel 80386 COFF object file, not stripped, 4 sections, symbol offset=0x102, 20 symbols, created Thu Jun 1 14:13:50 2023, 1st section name ".text"
Well, now that is interesting. And of course the COFF thing reminded me of Xenix! And sure enough ages ago I had found the source to a modified version of GNU GAS that outputs COFF. Once more again this is an indication that all 386 roads in Microsoft really did originate with Xenix. It’s too bad there never was a Windows/386 on Xenix/386. What an incredible OS that would have been! There must be some incredible stories from the tool teams that worked on Microsoft C/386 along with other projects. Oddly enough they never get anywhere near as much exposure as Office or OS.
Now this is fun, but nothing takes in these ancient COFF objects, do they? I tried to run LINK 1.0 from Win32s SDK and surprisingly it didn’t complain about the object, rather, it auto converted it in memory:
Microsoft (R) 32-Bit Executable Linker Version 1.00
Copyright (C) Microsoft Corp 1992-93. All rights reserved.
SIMPLE.OBJ : warning LNK4016: unresolved external symbol "__chkstk"
LINK : warning LNK4016: unresolved external symbol "_mainCRTStartup"
SIMPLE.OBJ : warning LNK4016: unresolved external symbol "_printf"
SIMPLE.exe : error LNK1120: 3 unresolved externals
Does this mean that if I give it some libraries it will actually link?
LINK.EXE SIMPLE.OBJ /SUBSYSTEM:CONSOLE /MACHINE:i386 -entry:mainCRTStartup -out:simple.exe libc.lib kernel32.lib
Microsoft (R) 32-Bit Executable Linker Version 1.00
Copyright (C) Microsoft Corp 1992-93. All rights reserved.
C:\temp\nt196\x\dec\x>simple
Win32, it's happenin'!
This was. VERY unexpected.
So I had this crazy idea, what if the Xenix assembler could in fact build objects that are also compaible in this manner? I used the a.out GCC / Linux porting tools I had built so I could compile Linux on Windows NT using the vintage tools as a starting point. I guess I should also add that when people always say ‘use newer version of THING’ this is how you miss out on old stuff like this. If I had been obsessed with using modern tools and modern operating systems, I’d have missed out on this Xenix filled window.
I took the gcc driver & the cc1 compiler from 1.40 and the c pre-processor from 2.5.8 as it can understand C++ comments. First I manually compiled the ‘simple’ example to assembly:
gcc -v -nostdinc -I/xenixnt/h -S SIMPLE.c -O simple.S
gcc version 1.40
cpp -nostdinc -v -I/xenixnt/h -undef -D__GNUC__ -Dunix -Di386 -D__unix__ -D__i386__ -D__OPTIMIZE__ SIMPLE.c C:/Users/jsteve/AppData/Local/Temp/cca2_048.cpp
GNU CPP version 2.5.8 (80386, BSD syntax)
#include "..." search starts here:
#include <...> search starts here:
/xenixnt/h
End of search list.
cc1 C:/Users/jsteve/AppData/Local/Temp/cca2_048.cpp -quiet -dumpbase SIMPLE.c -O -version -o SIMPLE.s
GNU C version 1.40 (80386, BSD syntax) compiled by GNU C version 5.1.0.
default target switches: -m80387
cpp -nostdinc -v -I/xenixnt/h -undef -D__GNUC__ -$ -Dunix -Di386 -D__unix__ -D__i386__ -D__OPTIMIZE__ simple.S C:/Users/jsteve/AppData/Local/Temp/cca2_048.s
GNU CPP version 2.5.8 (80386, BSD syntax)
#include "..." search starts here:
#include <...> search starts here:
/xenixnt/h
End of search list.
C:\temp\nt196\files\MSTOOLS\SAMPLES\SIMPLE>ax386 SIMPLE.s -o SIMPLE.obj
C:\temp\nt196\files\MSTOOLS\SAMPLES\SIMPLE>wsl file SIMPLE.obj
SIMPLE.obj: 8086 relocatable (Microsoft), "SIMPLE.c", 1st record data length 10, 2nd record type 0x88, 2nd record data length 11
Not quite the same. But it does closer resemble the output from the OS/2 bound versions of the Pre-Rease compilers:
file EMPTY.OBJ
EMPTY.OBJ: 8086 relocatable (Microsoft), "empty.c", 1st record data length 9, 2nd record type 0x88, 2nd record data length 7
So will it link?!
C:\temp\nt196\files\MSTOOLS\SAMPLES\SIMPLE>LINK.EXE SIMPLE.OBJ /SUBSYSTEM:CONSOLE /MACHINE:i386 -entry:mainCRTStartup -out:simple.exe libc.lib kernel32.lib
Microsoft (R) 32-Bit Incremental Linker Version 2.50
Copyright (C) Microsoft Corp 1992-94. All rights reserved.
SIMPLE.OBJ : warning LNK4033: converting object format from OMF to COFF
C:\temp\nt196\files\MSTOOLS\SAMPLES\SIMPLE>simple
Win32, it's happenin'!
Well now this is interesting! LONG before MinGW, or the GCC port to Windows NT, it turns out that in fact GCC could target Windows NT the entire time!
So the next thing to do is something not as trivial, like phoon.
I setup some quick script to pre-process, compile, assemble and then try to link, but as this one uses floating point, disaster struck:
Now ages ago while messgin with old GCC & DooM I also had weird math calls not working. In the end I ended up extracting them from libgcc builds, so I thought I’d try the libgcc built during the GCC 2.6.3 on NT adventure.
link /NODEFAULTLIB:libc.lib /NODEFAULTLIB:OLDNAMES.LIB -out:phoon.exe astro.obj date_p.obj phoon.obj -entry:mainCRTStartup libgcc1.lib LIBC.LIB KERNEL32.LIB
Microsoft (R) 32-Bit Incremental Linker Version 2.50
Copyright (C) Microsoft Corp 1992-94. All rights reserved.
And of course:
To try to make the steps make a little more sense, and to allow for some higher level of automation I made a Makefile:
I’m sure there is better ways to do this, but it breaks the compile up to it’s individual parts:
Run the pre-processor to allow // in the comments, C++ hadn’t been the default thing back when GCC 1.40 was a thing. Also path it to the headers, in this case I’m using the ones from NT 196. Trying to link with the 196 libraries gave me this:
C:\xenixnt\demos\phoon>link /NODEFAULTLIB:LIBC.LIB /NODEFAULTLIB:OLDNAMES.LIB -out:phoon.exe astro.obj date_p.obj phoon.obj -entry:mainCRTStartup base.lib wincrt.lib ntdll.lib \xenixnt\lib\libgcc1.lib
Microsoft (R) 32-Bit Incremental Linker Version 2.50
Copyright (C) Microsoft Corp 1992-94. All rights reserved.
wincrt.lib(maincrt0.obj) : warning LNK4078: multiple ".data" sections found with different attributes (40000040)
astro.obj : error LNK2001: unresolved external symbol "_asin"
astro.obj : error LNK2001: unresolved external symbol "_atan"
astro.obj : error LNK2001: unresolved external symbol "_atan2"
phoon.obj : error LNK2001: unresolved external symbol "_cos"
astro.obj : error LNK2001: unresolved external symbol "_cos"
astro.obj : error LNK2001: unresolved external symbol "_floor"
astro.obj : error LNK2001: unresolved external symbol "_sin"
phoon.obj : error LNK2001: unresolved external symbol "_sqrt"
astro.obj : error LNK2001: unresolved external symbol "_sqrt"
astro.obj : error LNK2001: unresolved external symbol "_tan"
phoon.exe : error LNK1120: 8 unresolved externals
Which is not surprising as there is no FPU/Floating point math support in 196. I tried the December 1991 Pre-Release, but it failed for other reasons:
I did copy over BASE.DLL BASERTL.DLL CSR.DLL DBGDLL.DLL as it wanted, but despite the symbol being in the DLL it didn’t load.
So that’s why I’m using the libraries from the Win32s SDK.
Okay, so far now we have GCC 1.40 compiling to an old Xenix GAS assembler, and linking with Microsoft link from Visual C++ 1.0/2.0 era. The next step is to see if we can just link the objects under 196, and get a running EXE!
I have this tiny fibonacci example program, so with it compiled & assembled by GCC & GAS, I did the final link under 196, and YES it runs!
Possible things to do? GCC should be able to build itself, so it should be possible to build GCC and link that on 196 or December 1991, and get a native version of GCC on NT. The other possibility is to get newer versions of GCC (cc1 drop in replacements) to build for Xenix and / or OS/2. Obviously this Xenix linker is the gateway to older 386 Microsoft based products!
With the pre-christmas release of the Microsoft OS/2 betas 1.00, 1.01, 1.02, 1.03 & 1.05 on archive.org, and helping Ncommander with an upcoming video, it seemed like a good place to start, not with OS/2 but rather with MS-DOS 4.0.
Microsoft started work on a multitasking version of MS-DOS in January 1983. At the time, it was internally called MS-DOS version 3.0. When a new version of the single-tasking MS-DOS was shipped under the name MS-DOS version 3.0, the multitasking version was renamed, internally, to MS-DOS version 4.0. A version of this product–a multitasking, real-mode only MS-DOS–was shipped as MS-DOS version 4.0. Because MS-DOS version 4.0 runs only in real mode, it can run on 8088 and 8086 machines as well as on 80286 machines. The limitations of the real mode environment make MS-DOS version 4.0 a specialized product. Although MS-DOS version 4.0 supports full preemptive multitasking, system memory is limited to the 640 KB available in real mode, with no swapping.2 This means that all processes have to fit into the single 640 KB memory area. Only one MS-DOS version 3.x compatible real mode application can be run; the other processes must be special MS-DOS version 4.0 processes that understand their environment and cooperate with the operating system to coexist peacefully with the single MS-DOS version 3.x real mode application.
Because of these restrictions, MS-DOS version 4.0 was not intended for general release, but as a platform for specific OEMs to support extended PC architectures. For example, a powerful telephone management system could be built into a PC by using special MS-DOS version 4.0 background processes to control the telephone equipment. The resulting machine could then be marketed as a “compatible MS-DOS 3 PC with a built-in superphone.” Although MS-DOS version 4.0 was released as a special OEM product, the project–now called MS-DOS version 5.0–continued. The goal was to take advantage of the protected mode of the 80286 to provide full general purpose multitasking without the limitations–as seen in MS-DOS version 4.0–of a real-mode only environment. Soon, Microsoft and IBM signed a Joint Development Agreement that provided for the design and development of MS-DOS version 5.0 (now called CP/DOS). The agreement is complex, but it basically provides for joint development and then subsequent joint ownership, with both companies holding full rights to the resulting product.
As the project neared completion, the marketing staffs looked at CP/DOS, nee DOS 5, nee DOS 4, nee DOS 3, and decided that it needed…you guessed it…a name change. As a result, the remainder of this book will discuss the design and function of an operating system called OS/2.
– Inside OS/2.
Although MS-DOS 4.00M disk images have been floating around for quite some time, either a 2 360k disk set, or a single 720k disk image, I don’t think anyone (including me) really tore into it that much. It does have the ability to freeze DOS 3 programs, giving the illusion of running more than one. The session manager is pretty sparse but hitting left alt twice will pop it up giving you the ability to toggle through programs with ease.
MS-DOS 4.00M
There is a FDISK, FORMAT & SYS command making it straight forward to setup a hard disk, and copy the files over, I didn’t see any installer.
there is a PS command to show running processes. Also there is a DOSSIZE to show the memory partitioning and how much is available. Although there is a SWAPPER program I’ve been unable to get it to actually fun.
multitasking!
Another interesting thing if you run the unix ‘strings’ command against all the EXE’s you’ll find the string:
C Library - (C)Copyright Microsoft Corp 1985
Implying that not only was DOS 4.00M a ‘new’ DOS, but it was also written in C. No doubt this contributed to a larger file size than DOS 3, however it would also give that holy grail of portability, at least to new CPU modes. Also many files have the name of the source files baked in such as:
Okay so far, so good. But we’ve all seen this before, and scratched this OS about this far, because what else can you do? It’s not like there is any dev tools to do anything fun!
Well the tool hidden in plain sight is LINK4, which in retrospect is specific for MS-DOS 4.00M.
Microsoft (R) 8086 Object Linker Version 4.01
Copyright (C) Microsoft Corp 1984, 1985. All rights reserved.
Object Modules [.OBJ]:
There is no SDK for MS-DOS 4.00M, but they were kind enough to leave the linker in place. A quick check of the Windows 1.01 SDK shows that it also includes LINK4:
Microsoft 8086 Object Linker
Version 4.00 (C) Copyright Microsoft Corp 1984, 1985
Object Modules [.OBJ]:
It appears that if the dates and versions are to be trusted they are of the same vintage, but the Windows linker is older, and that they both output to a NE or New Executable. So to start the experiment I created a simple hello world exe from a simple:
void main(){
printf("Hello from MSC 3\n");
}
To compile this I used Microsoft C 3.0 (more on why later), and used LINK4 to create an EXE:
C:\dos\msc3>cl /c hello.c
Microsoft C Compiler Version 3.00
(C)Copyright Microsoft Corp 1984 1985
hello.c
C:\dos\msc3>msdos dos4m\link4 hello.OBJ
Microsoft (R) 8086 Object Linker Version 4.01
Copyright (C) Microsoft Corp 1984, 1985. All rights reserved.
Run File [HELLO.EXE]:
List File [NUL.MAP]:
Libraries [.LIB]:
Definitions File [NUL.DEF]
Okay, everything looks fine so far. Attempting to run this under MS-DOS just results in the error:
Program too big to fit into memory
Well now that’s odd. Checking the EXE with the Linux ‘file’ command reveals:
file HELLO.EXE
HELLO.EXE: MS-DOS executable, NE (unknown OS 0) (EXE)
So obviously it’s a NE, but it is an older/unknown version to the file map database. There is no stub so I suppose that is why MS-DOS is getting confused.
Now let’s try MS-DOS 4.00M
Hello!
Well now isn’t that interesting?!
Excited with the ability to create special MS-DOS 4.00M programs, I get my favorite vintage ’87 Infocom interpreter, InfoTaskForce 87, and get it building on MSC 3.0. However instead of using the MS-DOS 4.00M linker, I thought I should try to use the Windows 1.01 linker and libraries for the exe:
NAME Infocom
DESCRIPTION 'Infocom 87 interpreter for Planetfall(83)'
DATA MULTIPLE
HEAPSIZE 1024 ; Must be non-zero to use Local memory manager
STACKSIZE 4096 ; Must be non-zero for SS == DS
; suggest 4k as minimum stacksize
SEGMENTS
_INIT PRELOAD MOVEABLE DISCARDABLE
One thing to save you the horror is that between MS-DOS 2 & 3 the way command line arguments changed. I forget the details but no matter what I tried I was unable to parse the CLI or the environment in this setup. I suppose if I had documentation of the product there would be some hint as to what tools or setup to use. Instead, I took the easy way and hard coded to load Planetfall.
InfoTaskForce compiled with MSC 3.0, using Windows 1.01 libc / LINK4
Unfortunately, this success would prove to be the exception to the rule. I took trek, converted it to K&R C, as Microsoft C 3.00 from 1985 is well. old, and sadly it just won’t run. Likewise, I took Hack 1.03 and although it runs on MS-DOS it will not run on MS-DOS 4.00M. I am sure there is some fundamental reason why it’s not working, and probably tied to creating a proper DEF file. I’m sure it was all written down somewhere but I don’t know. And yes I tried specifying either floating point emulation via library or inline, and it made no difference.
Looking at OS/2 1.00
Loading up the infamous $3,000 OS/2 1.00 beta, and hitting ctrl+escape you are greeted with session manager!
Session Manager for OS/2
Notice the R for real-mode. With the obvious implication that everything else is protected mode. Going one step further on the excellent site pcjs.org there is OS/2 betas SIZZLE and although there is no OS/2 development bits on there, the directory DOS3TOOL reveals that the C compiler for this era for at least MS-DOS is MSC 3.0. Also included is our friend LINK4.
I create a simple def file that contains the single word ‘PROTMODE’ which should give me my OS/2 binary.
So let’s run that through hello world:
msdos sizzle\DOS3TOOL\link4 hello.OBJ,hello,,,hello.def;
Microsoft (R) Segmented-Executable Linker Version 5.00.21
Copyright (C) Microsoft Corp 1984, 1985, 1986. All rights reserved.
C:\dos\msc3>
However attempting to run this just crashes amazingly.
Real mode LIBC in Protected mode:
No doubt it’s because the real-mode libc is using interrupt 21 calls, which OS/2 sure wouldn’t like. I’m pretty sure it requires an OS/2 libc that uses DOSCALLS.DLL to function, which I just don’t have any pre-release versions, nor any libc source code to really make it possible. And attempting to port one to OS/2 pre-releases just doesn’t seem so worth the time.
So for the heck of it I point the LIB variable to the OS/2 1.00 SDK’s libs and re-run the link:
C:\dos\msc3>msdos sizzle\DOS3TOOL\link4 hello.OBJ,hello.exe,hello.map,C:box0\x\MSC\LIB\slibc5.lib box0\x\LIB\DOSCALLS.LIB,hello.def;
Microsoft (R) Segmented-Executable Linker Version 5.00.21
Copyright (C) Microsoft Corp 1984, 1985, 1986. All rights reserved.
By default it’s trying to link in EM.LIB, SLIBFP.LIB, SLIBC.LIB. Trying to add them all in the command line link just hangs LINK4 maybe a response file is better suited. Anyways:
Hello from MSC 3.0 in protected mode.
It does run on OS/2 1.00, which I guess isn’t surprising as the LINK4 & libraries are from/for this version.
As an interesting note, OS/2 links against doscalls library/DLL to interface to the OS. While MS-DOS 4.00M doesn’t have a seperate DLL, rather it’s baked into IBMDOS.COM
Noticeably absent is file I/O, No doubt allowing programs to use the standard int21 interface to the kernel for file I/O. No doubt this is in its primordial state, as the OS was going to evolve a bit more until it became OS/2. Unfortunately I have no idea how to link or call into this. Without any SDK it’s impossible to say. And even then is developing for a real mode OS worth the effort?
So what have we learned? LINK4, aka the MS-DOS 4.00M Linker, probably should have been called LINKNE for the NE format. Also there is references to it having it’s own virtual memory paging system, and being able to link larger EXE’s than the traditional link command. Sadly I was unable to get any non trivial programs running. I don’t think it was a memory model thing, although the C compiler has issues with InfoTaskForce and the large memory model for some reason, but small & medium work fine. I’d like to think that DOS 4.00M could support massive EXE’s much like Windows 1.01, however despite being from the same company and using the same tools, the memory manager for DOS 4.00M & Windows is fundamentally different.
With all these exiting OS/2 betas now available I’ll have to take some more time to explore them in more detail.
But until then I thought this genesis of DOS 4.00M was worth the look.
I was so tired I ended up sleeping through the whole thing. Sometimes it’s hard being on the other side of the planet. But for anyone interested in Windows programming it’ll be super interesting in how much has changed, and yet how much things haven’t changed.
Damn!
As an added bonus, 65scribe has also blessed us with not only another great retrospective on iMacs, but also our favorite museum in Ontario, but left us with a cliff hanger (minor spoiler!).
Blue and Ice
I never knew about the artic blue ice thing before. Maybe it’s a coincidence, but who knows?!