• Please review our updated Terms and Rules here

CP/M Boot Sequence. Warm Boot issues.

cj7hawk

Veteran Member
Joined
Jan 25, 2022
Messages
1,124
Location
Perth, Western Australia.
Hi All,

So I've hit yet another problem - How should the CP/M Warm Boot sequence occur?

Cold boot is no problem, and warm boot presently runs via the BIOS which redirects to the CCP, but it all goes a bit funny when I start randomly switching BDOS and CCP on the fly between the ones I wrote and the DR originals.

And I'm having trouble figuring out if there's supposed to be anything within CP/M that supports this - as it can lead to crashes when it reboots at the end of running a program.

I can swap out the BDOS, but the DR BDOS is about 512K bigger, so where I made sure by FDOS always starts at F000, while the DR BDOS starts at somewhere around ED00 IIRC.

Meanwhile my CCP kicks in at D000, while the DR CCP starts at E500.

This leads to problems with the warm boot vectors when I switch CCP or BDOS on the fly. Switching is no problem, and switching back I just cold boot, but when I have a warm boot then the vectors are all messed up. CP/M seems to ignore BIOS+0 as a vector, and the BIOS has no idea where the BDOS or CCP is.

Were there any conventions to relocate a warm boot vector to a specific location in CP/M? eg, like the BDOS vector at 0005 ?

Or was the likelihood of someone replacing the BDOS/CCP so low that it was always addressed with patching or source code changes?

David.
 
This is written from my brain's recollection of a CP/M port from many, many years ago I did - so some of my neurons may have become faulty in the intervening time... This is related to one particular revision of CP/M (V2.0 I think), or was it 1.4 or 2.2?

From what I remember, there is a relationship between the CCP, BDOS and BIOS addresses. The BIAS ('b') is calculated based upon the offset of the CCP from a distribution 20K memory implementation. The BDOS and BIOS addresses are then calculated based upon a knowledge of their sizes.

However, I think these should be 'hard encoded' within your BIOS - so they could be changed accordingly.

I think the key thing (after performing the track load into memory) is to reset various things up in low memory:

The JMP (0xC3) instruction at addresses 0x0000 and 0x0005.

The entry point to the Warm Boot code at address 0x0001 and 0x0002.

The entry point to the BDOS at addresses 0x0006 and 0x0007.

You should also set the default DMA address to address 0x0080.

And (finally) set register C to the currently selected disk and enter the CCP.

I would have though that this should be enough - but...

I would have thought that the standard CCP and BDOS would have used the vectors in addresses 0x0001/0x0002 (BIOS WBOOT entry point) and 0x0006/0x0007 (BDOS entry point) and to (re)use these on a warm start. I assume your replacements are doing the same?

Dave
 
Last edited:
I actually didn't think of that - that seems like an elegant solution - Set the vector at 0001 to the CCP directly instead of via the BIOS or BDOS. For some reason I was fixated on the idea that the vector at 0001 should ideally go to the BIOS, but that's not necessary unless I'm performing a cold boot and am reloading both the BDOS and the CCP.

There there's no need for the BIOS to know where the BDOS is ( it's at 0006 of course ) and the CCP is at the vector at 0001.

The BDOS of course never moves so it is hard coded into both.

That should work as my cold boot is handled via the BIOS or by anything that sends the appropriate bit set to the appropriate port.

It would also let me change the BDOS and the CCP on the fly, since

Did I understand the suggestion correctly?

I have three possible reset vectors so that would leave two of them going to the CCP by default. - I have RST0 ( and any JMP 0 ) as one, a physical RST 0 via external interrupt which could be redirected in hardware if required to a different page, and the physical reset line, which pages in the cold boot rom.

Does anything in CP/M look for the BIOS location via the vector at 0001? There was something nagging in my mind that told me it did, but I may have been confusing it with the 0006 vector. If it's only the BDOS, that needs to know where the BIOS jump table is then I'm good to go :) And I can always store the BIOS vector in the zero page in a space location.

Thanks
David.
 
If you alter the normal relationship of the addresses for the warm boot JMP at 0 and the BDOS entry JMP at 5, you can get into trouble. The BDOS entry JMP is also used as the "top of available memory" address, which means programs are free to use memory from 0100H to that address (-1). If you have the JMP at 0 referencing memory that sits below that address (e.g. CCP), you will crash on warm boot.

DRI really left the details of booting up to the vendors, however that relationship of the memory layout between BIOS, BDOS, and CCP really is pervasive. The standard warm boot procedure is to enter the BIOS warm boot JMP (typically directly via the JMP at 0) from which point the BDOS and CCP are reloaded (from whatever source media and at addresses based on whatever "knowledge" the vendor's BIOS wants to employ) and the BIOS jumps to CCP+3. The standard CCP has two JMP entries, CCP+0 is the cold boot one and mainly differs by honoring a possible startup command pre-loaded into the command buffer, whereas CCP+3 clears the command buffer and starts the CCP normally.

The reason both BDOS and CCP are reloaded is because it was permissible for a program to consume more memory by also overwriting the BDOS (if it didn't need BDOS facilities), using the warm boot JMP at 0 as a reference to the upper limit of memory.
 
And, yes, the BIOS JMP vectors must be represented by the JMP at 0. This is used by programs that call the BIOS directly.
 
>>> Did I understand the suggestion correctly?

Er, no...

Addresses 1 & 2 should point to the BIOS Warm Boot and addresses 5 and 6 should point to the start of the BDOS (entry point and top of usable memory - as Doug states).

What I was asking is are these two vectors set up correctly following your 'swapping' and do you use these vectors (after setting them up) to refer to the BIOS and BDOS entry points as required?

Dave
 
And, yes, the BIOS JMP vectors must be represented by the JMP at 0. This is used by programs that call the BIOS directly.
This is one of the things that I was worried about.
DRI really left the details of booting up to the vendors, however that relationship of the memory layout between BIOS, BDOS, and CCP really is pervasive.
And this is the other thing I was worried about... :(

Looks like I need to add another vector to the zero page and reference it from the BIOS, which I really didn't want to do. Otherwise it's difficult for the BIOS to keep track of where the CCP is loaded if I randomly change which CCP or BDOS I'm using during normal operation.

Does CP/M of any version do anything specific with the reserved space between 0040 and 005B? At the moment I've extended two pseudo-interrupts at 0040 and 0048 for video and network, and I have a return-from-process hook at 0050. None of that really matters if the BDOS/CCP is changed, but where I put a vector for the warm boot is a little more critical.

Thanks
David
 
Normally, the only thing that accesses the CCP is the BIOS during warm boot. That probably should not change. When the BIOS reloads the CCP, it may get the address from the media used to load the CCP. For example, some vendors have a boot sector that contains various addresses and sizes of the components. Or if loading the CCP from a file, there could be clues as to the load address (and/or size) in there. Dynamic switching of the BDOS and CCP is possible, with the right information made available to the BIOS warm boot routine. I would not suggest trying to swap-out BDOS or CCP any time other than warm boot. So are you thinking of have some BIOS call or structure that dictates which BDOS and CCP to be used, which takes effect on the next warm boot? BTW, it was common for vendors to define an area of the BIOS first page beyond the JMP vectors for vendor-specific data and functions.
 
>>> Did I understand the suggestion correctly?

Er, no...

Addresses 1 & 2 should point to the BIOS Warm Boot and addresses 5 and 6 should point to the start of the BDOS (entry point and top of usable memory - as Doug states).

What I was asking is are these two vectors set up correctly following your 'swapping' and do you use these vectors (after setting them up) to refer to the BIOS and BDOS entry points as required?

Dave
Yes, I have them set up correctly, but when I warm boot after changing the BDOS or CCP, then there's an issue for the software in finding the CCP.

The vector for the BIOS and BDOS are well defined, but there is no vector for the CCP for a warm boot - and I don't necessarily want to rewrite the BDOS/CCP on a warm boot, because they may have changed from the default warm boot versions. At the moment I'm using it for testing mainly, so I can switch between LokiOS and CP/M to make sure software works correctly with both, but it's leading to instability post warm-reset.

I tried to figure it out myself but it's a less easily found attribute of CP/M in the DR documentation. :(

Then I noted that the BDOS I have from DR doesn't jump to the BIOS - It jumps straight to the CCP.

I wasn't 100% certain about the two jumps in the CCP either, which Doug clarified, which helps... Right about now, I'm kind of wishing I documented my journey into CP/M a little more solidly... It's quite an experience coming late into CP/M and discovering all of the things that aren't mentioned in many of the texts I'm learning from...

I don't mind varying from CP/M - after all, it's a CP/M compatible OS I'm writing, not just a rehash of CP/M... But little things like losing functionality after a program exits due to the warm boot are frustrating....

Earlier this week I had other challenges, such as the video drivers not loading under CP/M, or the order of loading eg, Switch to CP/M then load video driver works, load video drive then switch to CP/M didn't. Not to mention the fun with paging out the stack and wondering why my loops are going crazy.

But my OS and architecture are starting to firm up a bit and get more resilient. Most software runs OK now, and I'm not corrupting disks as often. Also I'm doing some "undocumented" things with the original CP/M such as deliberately creating cross-linked files, which surprisingly, the BDOS actually resists!.... I really didn't expect it to do that, especially as it doesn't check for that.

Finding solutions to my problems is easy. Finding solutions to my problems that don't cause issues if I switch CP/M version on the fly is more challenging than I thought it would be.

David
 
What I'm saying is that the entry point for BDOS and CCP - during warm boot - should NOT be determined by existing JMPs at 0 and 5. That needs to be something associated with the actual BDOS and CCP images being loaded. You will need to change the JMP at 5 when changing the BDOS. The normal actions taken place in BIOS warm boot are to re-create all of page 0 ( at least parts that are critical, JMP at 0 and 5, IOByte, default drive). This becomes more important if the BDOS and CCP are changing.
 
Normally, the only thing that accesses the CCP is the BIOS during warm boot. That probably should not change. When the BIOS reloads the CCP, it may get the address from the media used to load the CCP. For example, some vendors have a boot sector that contains various addresses and sizes of the components. Or if loading the CCP from a file, there could be clues as to the load address (and/or size) in there. Dynamic switching of the BDOS and CCP is possible, with the right information made available to the BIOS warm boot routine. I would not suggest trying to swap-out BDOS or CCP any time other than warm boot. So are you thinking of have some BIOS call or structure that dictates which BDOS and CCP to be used, which takes effect on the next warm boot? BTW, it was common for vendors to define an area of the BIOS first page beyond the JMP vectors for vendor-specific data and functions.
That's a good point. I have a few spare bytes at BIOS+0030 since I start my DPB tables at BIOS+0040 so they are easy to spot in the monitor. I suppose I could use that space as well, and while it occured to me, I wasn't sure if it was a good idea.

In my case, the BIOS is the first 4K of the "DISK" Eprom for L: drive, which I locate at F0000 - and I relocate that to CPU address 0000 on cold boot. There's a 256 byte bootstrap which load the BIOS into RAM at FC00, then the BDOS into RAM at F000, which leaves a gap at FB00 where I store scratchpad information, which may be problematic if programs sometimes obliterate it, though in fairness, the scratchpad is mostly used by the BDOS since it has little relevance to the BIOS. Then I store the global stack at FFFF, though I am quickly learning most CP/M programs not only don't care, they always seem to put the stack wherever I am going to page it out, so protecting the stack was a major bugfix I had to add to the driver system.

The driver system works by convention, and takes 8 bytes to switch process ID and jump to the start, typically at 1000 (Page1 start) but that's just a convention of convenience since it's difficult to access the MMU safely post-boot. The drivers can technically access the stack anywhere, but it's simpler to follow the convention, and that lets me put the video bios and video bitmap raster outside of the 64K memory space entirely and call it via a call to 0040 without interfering with the executing program in any way, which maximises space available to the program... I left the BDOS in memory, but in truth that can be paged out also, or swapped with hooks, but the software DMA requirements get in the way a bit with disk access if that is done and increase complexity./

So with all of that, there's no way to boot a different OS into the system - It boots with LokiOS, straight off the rom, installs the video driver and sets up the MMU and memory management disk ( M: drive ) and then drops straight into the command line.

Hence I need a way to allow BDOS/CCP upgrades and version changes without having to swap the ROM, so I just package the binaries with an installer than switches it in when it is desired, hence the BDOS or CCP from any version can be switched in - though of course, some CCP won't run if the BDOS serial doesn't match, but if the startup routines on L: detect a valid OS and know it is preferred, then it's not much more to install that OS update too, so theoretically, it could switch to CP/M 1, 1.4, 2, 2.2 or 3 on the fly... Well, I'm not too sure about 3. The BIOS may be insufficient, but then again, the whole thing is in RAM, so it should be possible somehow. And it needs to be able to happen on the fly too, since rebooting is not an option unless it's a reboot then a deliberate loading of only one OS.

And of course, It's all running in an emulator still, as I switched from Hardware design to OS design, which turned out to be a good decision, as the OS requirements are constantly changing the demands on the hardware and I'm learning as I go. But I was pretty happy when the Infocom adventures started working, and when Wordstar could clear the screen and operate correctly with the ADM-3A codes it was sent.

I don't even want to think about what kinds of problems I might hit when I shift it to actual hardware... I am still making major changes there - most recently decided to go with ISA bus since it has the Interrupts all layed out nicely... And I suppose BIOS roms not withstanding, it means PC ISA cards ( eg, Serial, Parallel, CGA and maybe even VGA ) should all work on the z80 system. All with a passive backplace and memory located on a different card to the CPU/MMU/BasicDMA etc.

I'm pretty sure I thought I'd have this all done in a couple of weeks when I started :( I did that with a science fiction book about AI that I wrote once. Supposed to be a short story. Then a novellette. Then a short novel... Ended up a decent sized novel that took me two years to write and clean up... Then a few more years to get properly published.

This project is very much starting to feel the same.
 
What I'm saying is that the entry point for BDOS and CCP - during warm boot - should NOT be determined by existing JMPs at 0 and 5. That needs to be something associated with the actual BDOS and CCP images being loaded. You will need to change the JMP at 5 when changing the BDOS. The normal actions taken place in BIOS warm boot are to re-create all of page 0 ( at least parts that are critical, JMP at 0 and 5, IOByte, default drive). This becomes more important if the BDOS and CCP are changing.

Yes, I am changing the BDOS hook when I load in the new BDOS - that much works pretty well since all BIOS functions are accessed via 0005 and the BDOS knows exactly where the BIOS is.

Actually changing between OS elements itself on the fly is working pretty well, but only from the boot. I still have to solve the first-warm-boot issue I created myself.

Because a cold boot reloads the BDOS, I'm changing page 0 in the BDOS, which does things like shoves RETI statements in at all RST locations, and cleans out the DMA area and prepares the FCB at 005C.. Should the normal BIOS also rebuild all of the zero page? I can protect the zero page and restore it easily enough, but would prefer to leave it as is on a warm boot. So far, I haven't found anything that corrupts it unintentionally.

I figure programmers might want to install stuff there that persists between warm boots, and it's very easy to switch from a warm boot to a cold boot and reload everything since it's all in ROM-disk. Well, at least unless someone is loading a new OS from a physical drive.

Or at least, I haven't found anything yet in the CCP/BDOS that corrupts the zero page. Is that something that is likely?
 
Back
Top