Saturday, October 20, 2012

MUXX: Milestone 2 reached

My toy kernel slowly evolves...

This morning I have considered my little toy PDP-11 kernel has reached the second milestone. This means that right now my creature has the following super-advanced features:

  • It can open and close channels to devices (currently just the paper tape puncher and reader and the line printer).
  • It can read and write using those channels, in synchronous mode (no context switch when a task blocks for a read... it spins faithfully until the I/O operation is complete).
  • It can load tasks from a channel and execute those tasks in a separate, memory protected address space. 
The next goal is to pull some functionality out of the kernel space and move it to different processes. At that point I will be able to say without being ashamed of myself that MUXX has a microkernel architecture... :) And I really must do it, because the current version is just at the limit of the 24KB I defined as kernel code space. So, the next steps will be:

  • Define a framework of inter-processes message passing and replying (I will probably inspire myself on minix to do this).
  • Decide which kernel functionality I will move to the auxiliary processes without breaking it all. It will be probably the memory management and the error/message handling.
I have swapped milestones 3 and 4. My original plan was to get interrupt-driven asynchronous I/O first, but right now I can't stuff anything else in the kernel space. On the other hand, the asynchcronous I/O implementation could and will use separated processes and inter-task messaging, so it makes much more sense to do it in this order.

About process creation and task loading

As I wrote when I presented this project, my goal is to learn about operating system implementation as well as to known better the PDP-11 architecture. I have to say I am progressing in both goals. A lot.


Lets put an example. The load() function. This funcion loads a task image from a channel and puts it into memory. When I started I planned it to be a syscall. It IS a syscall in some operating systems (in particular, MVS or z/OS, as you want to call that thing). In UNIX there is not a load() function, but a family of exec() functions which do (aproximately) the same function.

The UNIX operating system uses a somehow curious way to create a new task. To create a new task (or process) you must use the fork() system call, which basically duplicates the executing task. Then this function returns a different result for the "parent" task (in this case it returns the ID of the created process) and the "child" or "new" task (it returns NULL). Then the parent task can go on with its own business, while the "new" one can call the exec() function to load a new executable and transfer control to it. 

In contrast, MUXX has a different model, inspired in VMS. In that wonderful operating system the parent task uses the CREPRC syscall to build a new address space and load an image into it, just in one step. There is no "forking": the new process does not begin its existance as a copy of the parent. In MUXX the CREPRC system call does create a new address space and does set up its corresponding memory pages, but it does not load an image into it. It assumes the new process will execute some code already present in the kernel image (so the new task is hard-linked into the kernel). The reason to do it this way is really simple: during the development of MUXX I needed to be able to create new tasks before I could think about loading different, separated images. So CREPRC just creates and branches, but does not load.

So here comes LOADPRC, a second syscall which does load a new image. And now comes the problem: the MUXX kernel is not preemptable at this moment. That means that the kernel code (so the syscalls) executes with the interrupts disabled. And to do a potentially long (in terms of elapsed time) operation like an  image load with interrupts (and hence task switching) disabled is really an ugly solution. That means, basically, that the actual loading of the new image has to be performed in user mode, out of the kernel space.

This brings us into another problem. We are loading an image into a new task, what means different memory configuration (different MMU setup)... from user mode code and from (probably) a non-privileged task. I could probably have written some kludge to do the MMU config switching during the LOAD, but I felt a little bit lazy about it, so I decided to use another aproximation. Enters rshell.

rshell comes from resident shell. It will evolve to be the "resident" part of the system shell (the part which will be present in memory at all the time), and is hard-linked with the kernel code, so it has to live in the low 24KB of memory. Right now rshell is really simple. It does just one thing: it looks at the task memory base (at 060000 octal) for a device name (in the future it will be a file specification) and calls load() to read that task into memory (beginning at 060000!). load() is a library function, not a syscall, and executes mostly in user mode (except for the actual I/O). When/if the load is completed, rshell jumps to the address 060000, where the linker has located the crt0() function, which in turn initializes the runtime and calls the main() function for the task we are loading. 

The nice part of this is rshell executes in the new task address space. So when a program invokes LOADPRC it does the following:
  • It prepares a new task address space, just like CREPRC does.
  • It copies the name of the image to load at the position 060000 of the new address space
  • It prepares the new task to begin its execution at the rshell() entry point
And that's it. When the scheduler selects the new task to execute it will run rshell, which will load the new image and transfer control to it... Of course, right now MUXX can use just the paper tape reader, so there are concurrency problems (if we try to run 3 tasks they will try to load at the same time...), but those are workable.

About the MMU setup and MUXX memory model

When I started loading tasks at their own address (beginning at 060000) I begun experiencing weird and hard to explain crashes. They came in all flavours: Illegal instructions, odd memory accesses, MMU exceptions... I really had no idea about what was happening, but they just occurred when I started the tasks using LOADPRC (if I linked the same tasks into the kernel and ran them using CREPRC they did fine). After some investigation, I realized the code resident at the page 6 (060000-080000) was being overwritten, so when the execution got transferred to the corrupted position all kinds of Bad Things happened. Observing the overwritten areas they seemed to be clobbered by printf()... so I spent a pair of days trying to find some bug there.

I obtained printf() from the 2.11BSD libc, with some minor changes to adapt the BSD code to MUXX ABI. I had previously found some stupid bugs in my minor changes, but I thought it was now correct. After some hours of work, I decided printf() was doing fine, so the problem had to be somewhere else. And that somewhere else happened to be precisely here. Let's take a closer look at that.

MUXX task memory map

The muxx_memsvc_svc.c module contains the basic memory management code. If you look at the linked version you'll see it is incomplete (right now the memory deallocation is not implemented yet).One of the things that module does is to set up the address space for a new task. That is what muxx_setup_taskmem() does.

A MUXX task address space has three (or four) different memory regions:
  • 000000 to 057777 is the kernel space, shared by all the tasks. It is write-protected from user mode code (except for the tasks with operprv privilege and the system tasks). 
  • 060000 to 137777 is the user space. CREPRC and LOADPRC allows to select between three task sizes (SMALL, MED and LARGE), which correspond to real user spaces up to 077777, 117777 or 137777 respectively.
  • 0150000 to 157777 is the stack space, furtherly divided at 156000 between user mode stack and kernel mode stack
The space between 137777 and 150000 is not allocated at this point. It will be used when I implement different stack sizes.

The fourth region, between 160000 and 177777 is the mapped IO area, and it is not mapped into the user mode address space unless the task has the ioprv privilege.


PDP-11 memory management

The PDP-11 program-accessible address space is, then, a 65566 position array of bytes, or a 32768 array of words. The physical memory addressing capability of the PDP11 depends on the model and goes up to 2048 Kbytes. The model I am targeting, the 11-60, has a 256KB addressable space. The MMU allows the PDP to map those 256KB so they cant be seen through the 64KB address space. When the MMU is enabled, the addresses the programs work with are virtual addresses which must be relocated to real, physical addresses. Using the MMU we can provide different relocations for different tasks, so each task gets its own 64KB address space, with or without sharing memory with other tasks.

A 16-bit virtual address is formed by two parts:
  • The highest 3 bits form a number from 0 to 7 which tells us what "page register" will we use to relocate the address.
  • The lowest 13 bits form a displacement inside a 8192 bytes "page".
The MMU has a bunch of registers to configure the memory relocation. These registers are grouped into two or three sets corresponding to the processor execution modes (user, kernel and, in some models, supervisor). The processor models with separate I and D address spaces double the number of registers. Our PDP-11/60 has just two sets for user mode and kernel mode. Each set contains eigth pairs of registers, each of those pairs corresponding to one "page" between 0 and 7. And each pair is composed by a page address register (PAR) and a page descriptor register (PDR). Each PAR contains a number of physical memory block, being each block formed by 64 bytes. The PDR contain control information, like the access permissions for the page they describe, the size of the block and some other information, particulary the growth direction, which tells the MMU if the accesses will be done upwards (like in normal code or data arrays) or downwards (like in a stack).

Lets say our program refers to the virtual address 060042. That address breaks into:
  • A page number in bits 13-15, which is 03.
  • A displacement in bits 0-12, which is 42.
That means the MMU will use the PAR and PDR for the page 03 of the current mode. We will ignore the PDR at this moment. Let's say the PAR for the page 03 contains the value 01200. Then, the physical direction will be formed this way:
  • Physical address base: 01200 * 0100 = 0120000 (remember we are using octal figures)
  • Displacement: 042
  • Physical address: 0120042
That will be the real address the CPU will reference. Changing the values of the PAR we can assign the same virtual address to different physical addresses, efectively isolating the tasks from each other. Manipulating the PDR we can establish protection for the memory pages, so the user mode code can't write into the kernel space or can't even see the IO mapped addresses.

The MMU can also detect when we try to access a memory address which is out of the mapped range. The PDR contains a field with the length (in blocks) of the current page. So, if  we confugure it with a 4KB memory page and we reference a position at that page with a displacement grearter than 4KB, the MMU forces a memory trap and invokes a handler using the usual PDP-11 trap sequence; this allows an operating system to do something about that, being it just killing the offending task, invoking some paging mechanism or panicking if the trap has occurred in kernel space.

Now you can tell me a liar. I've omitted that pesky "growth direction" bit in the PDR. If that bit is set then we are telling the MMU that the page grows downward, and then the size check works just the opposite way. That means in our exemple of a 4KB page it would trigger a trap if we referred to a virtual memory with a displacement less than 4KB! In MUXX the stack resides in a 4KB page, so if we grow the stack below that 4KB line, it will trigger the trap and will abort the task (currently, it panics the system, since MUXX does not know how to kill a task yet)

Misunderstanding the MMU and learning it the hard way

Let's look at the stack preparing code in muxx_setup_taskmem:


  /*
  ** Task stack space
  ** The stack size options should be evaluated and applied here
  ** Since the stack grows downward, the PAR contains Addr - Size 
  ** so the physical addresses are properly calculated without
  ** overlapping.
  **
  ** Example: Base virtual address: 0140000
  **          Top of stack:         0157777 (0120000 + 020000 - 1)
  **          Bottom of stack:      0150000 (0120000 + 010000 )
  **          PAR value:            0500
  **          Size:                 0100 (4K)
  **          Physical range:       060000:067777   
  */
  mcb = muxx_mem_getblock(task, 0100, MMCB_FLG_STK, 6);
  if (mcb != NULL) {
    task->mmuState.upar[6] = mcb->blockAddr-0100;
    task->mmuState.updr[6] = PDR_ACC_RW | PDR_SIZ_4K | PDR_DIR_DN;
    task->mmuState.kpar[6] = mcb->blockAddr-0100;
    task->mmuState.kpdr[6] = PDR_ACC_RW | PDR_SIZ_4K | PDR_DIR_DN;
  } else {
    return (ENOMEM);
  }

Don't you find anything unusual? Let's check the previous, bugged code:
  /*
  ** Task stack space
  ** The stack size options should be evaluated and applied here
  */
  mcb = muxx_mem_getblock(task, 0100, MMCB_FLG_STK, 6);
  if (mcb != NULL) {
    task->mmuState.upar[6] = mcb->blockAddr;
    task->mmuState.updr[6] = PDR_ACC_RW | PDR_SIZ_4K | PDR_DIR_DN;
    task->mmuState.kpar[6] = mcb->blockAddr;
    task->mmuState.kpdr[6] = PDR_ACC_RW | PDR_SIZ_4K | PDR_DIR_DN;
  } else {
    return (ENOMEM);
  }

Do you see the difference? In the corrected code I'm substracting 0100 from the PAR value for the stack page. So if I'm allocating the addresses 140000-150000 to the stack, I'm not writing 1400 in the PAR, but 1300. Why? 

The top of the stack for the kernel mode code is at 157777. That is, page 6, displacement 17777. If I put 1400 in the PAR this translates to 140000 + 17777 = 157777. Since the stack PDR is configure with the "grow downwards" bit, the MMU will not complain about this relocation and when MUXX writes something in the stack, it will clobber the 157777 physical memory address.

Of course, our stack is 4KB big, so we have just allocated 0100 blocks for it. And we have allocated the next available blocks to the next created task (since the stack is the last page we set up). So the next page will have probably the blocks 1500 to 1700 (for a 8K so 200 blocks page). Now we can see the problem. The stack of this task is sharing the same memory blocks of some page of the next created task. And that is precisely what we see... the 03 page of the next task (the one which will be allocated first!) is clobbed by our current task writing into its stack! 

The solution is to pull back the content we write in the PAR by 0100, corresponding to the 4KB size we are not allocating to the stack. Redoing the numbers, the 157777 virtual address would relocate into block 1300 plus displacement 17777 = 147777, which is just in the 1400-1477 range. If we go down 140000 the MMU will detect it and will trigger a trap, so we are safe. The weird thing is that in our memory management tables we will register the stack uses the pages  1400-1477, while the PAR will contain 1300. Weird, but correct.

Going on, and small machines...

And that is all for today. As unrelated stuff, my raspberry holds now 6 simulations: 2 VAXen, 3 PDP-11s (RSXM, RSXM+ and RSTS) and PDP-10... without a lot of load, but they work. For those of you who are part of HECNET, remember those machines are in area 7 and most of them have GUEST accounts, You will be welcome at my humble simulated, rapsberryzed digital home.

Monday, September 17, 2012

New toy...

This is going to be a short post... I've just got a little nice toy, and I've moved 3 of my SIMH machines to it. 


Yes, it is a Raspberry PI. And right now it is hosting three simulated machines: a VAX 780 running VMS 4.7 (and working as area router for my HecNet link), a microVAX 3900 running openVMS 7.3 and a PDP-11 running RSX11-MPlus 4.6. Of course, the simulated machines are idle most of the time, otherwise I guess they would overwhelm the poor raspberry...

To make it run, I have cloned the SIMH git repository from http://github.com/simh/simh, and before compiling it I've installed the packages for libpcap and vde2 (if you are going to do this, don't forget you have to install the -dev packages). SIMH compiled without any complaint, and once I got the simulated machines copied to the USB pendrive I've plugged to the thingy, they booted without a hassle.

After that, I just edited /etc/networking/interfaces so the vde magic gets configured at boot time:


auto lo

iface lo inet loopback

#iface eth0 inet dhcp

auto eth0
     iface eth0 inet static

auto tap0
     iface tap0 inet manual
     vde2-switch -t tap0 -n 16 -s /tmp/vde.ctl -M /tmp/vde.mgmt -m 666 --mgmtmode 666 

auto br0
     iface br0 inet static
     address 192.168.0.8
     network 192.168.0.0
     netmask 255.255.255.0
     broadcast 192.168.0.255
     gateway 192.168.0.128
     bridge_ports eth0 tap0             


And that is basically all (I'm using a static IP address bound to br0... the default configuration for the debian-based distribution I'm using is to use DHCP).

Not bad for a 35€ little computer...




Thursday, September 6, 2012

Writing a kernel: I'm falling in love with the PDP-11 architecture

You are doing WHAT?

So the crazyness goes on. I have decided to learn to program in PDP-11 assembly language, and the way I'm doing it is writing a sort of operating system for that platform. I did some OS practices in my college time, but they were based on x86, and were limited to create a real mode (no memory protection!) multitasker. At work I have no reason to do kernel level programming (although I've done some systems level stuff for the IBM mainframe), so I was somehow lacking on OS knowledge.

First of all, my work is completely public. I'm publishing my code at github. The public repository is https://github.com/jguillaumes/muxx MUXX is the name of the toy operating system (Mostly Useless eXperimental eXecutive). I have got to build some tools to manage the SIMH paper tape loading format, which can be found at https://github.com/jguillaumes/retroutils. Feel free to take a look at the code and partake anything you find useful. 

The big picture

MUXX is basically a vehicle for my enjoyement. So it will be probably full of design flaws, underoptimal implementations and failed decisions. Lets see what it IS and what it IS NOT:
  • It will NOT be a UNIX clone.
  • It will have a microkernel structure. Basically, that means that some of the low-level functions will reside in separated tasks with separated address spaces; some of those tasks will be the memory management and some of the device drivers, including the console, multiplexer, paper tape and flopply drivers.
  • It will be written in assembly code and C (not because I like it, but because there is no option that I know of building a cross-compiler for the PDP-11 capable of generating systems level code).
  • The target, emulated machine will be a PDP 11/60 with 256 KW of memory. The only reason for that is that was the only PDP11 I worked with, something like  25 years ago...
MUXX will use memory management (it will be a mapped system), and will run in kernel and user modes. It will not use supervisor mode (at least at the beginning), neither I/D space separation, although I will try to code the necessary hooks to implement those features. 

Development milestones.

There is a doc subdirectory in the MUXX public git repository, which contains some documents about what I am doing. The milestones.odt document lists my development plan (of course subject to changes... that's the good part of being project manager/analyst/system programmer/technical writer all at the same time). I have set up a series of milestones I'm planning to follow, which are (copied straight from the document):

  • Milestone 0: Console I/O, MMU enablement and mapping, system calls using TRAP or EMT, switching to/from user mode via RTS and traps. Already achieved.
  • Milestone 1: Clock interrupt. “AAA/BBB” task switching, with full context management. Human-readable trap/abort messages. Basic memory management (embedded in kernel). Tasks “A” and “B” still linked into kernel. Achieved.
  • Milestone 2: Device Driver framework. Programmed mode paper tape device driver (read only and synchronous). Tasks “A” and “B” loaded from LDA image on paper tape. Tasks loading will be hardcoded at kernel startup, but the tasks will not be linked into the kernel.
  • Milestone 3: Interrupt-driven paper tape device driver. Tasks “A” and “B” loaded from paper tape. The task loading will be still hardcoded.
  • Milestone 4: Memory management out of kernel, in privileged task. Message switching between tasks
  • Milestone 5: Interrupt-driven console device driver. Basic command interpreter (“TASKS”, “LOADA”, “LOADB”, “STOPA” and “STOPB” commands. Loading of tasks “A” and “B” moved out of the startup code.
  • Milestone 6: Interrupt-driven multiplexer device driver (probably DZ11). Tasks “A” and “B” running in different terminals. Several instances of the tasks (up to number of terminals) will be started from the console.
At this time I've achieved milestone 1, so I have a working multitasker, with full memory protection and (sort of) meaningful abort/panic messages. The only device MUXX knows off at this time is the console (DL11), and just for output; that output is done in synchronous mode (so the kernel loops until the I/O operation is done). I have also written a basic "read character" rountine, which is also synchronous, so it can't be used seriously in a multitasking kernel... but I'll overcome this limitation when I reach milestone 5... some day.

Sources of "inspiration"

I don't want to write just another UNIX clone. We have perhaps too many of those. My plan is to learn about OS design and implementantion, and to have fun. Having said that, there is a lot of useful information around. My main sources for... inspiration are:
  • Andy Tannenbaum's book. Yeah, the blue brick. Both the text and the minix sources are really good sources of information. And it is written to be easy to learn from. I'm taking the whole microkernel and message passing ideas from minix.
  • The PDP-11 Handbook. The basic reference book about the PDP-11 architecture. It covers mostly all you need to program the '11: instruction set, interrupt handling, memory managing and basic programming techiques.
  • The PDP-11 peripherals handbook. It contains the information needed to write device drivers: I/O mappings, interrupt vector numbers and control register description. The version I've found in the net is not the last one, and several devices available in SIMH are not covered, but it will be enough to begin.
  • The 2.11BSD system source code.The best way to solve a problem is to look how someone else did solve it before you. Of course you can also set up your own 2.11BSD simulated machine if you want to, but it is probably easier to browse the source code from the linked site.

Tools

The development is being done in a linux machine, so we need some cross-development tools. My previous entry talked about building a PDP-11 cross-assembler. I progressed a little bit since I wrote that. Most of the information I wrote is valid. I've built the tools from the git repositories. The GCC git repository can be found here. The binutils repository is this one.
If you have read the previous entry perhaps you remember I had a quite weird problem with the linker, which failed to create pdp11 binaries. It complained about a syntax error in the default linking script. Although this is not a showstopper (I use a customized link script to build the kernel), it is annoying. The solutuion was ridiculously easy: you MUST use a "clean" environment to build binutils and gcc. By "clean" I mean you must erase some environment variables which interfere in the linking process: LIBPATH, SHLIB_PATH were the culprits in my case. If you plan to build the cross-building tools, check your environment for related variables.
I also found a bug in the gas assembler. I submited it to the binutils bugzilla.The problem is gas assembles this instruction:

         jsr    pc,@(R0)
Like:
        jsr    pc,(R0)
Instead of
        jsr    pc,@0(R0)

Unfortunately, the gcc compiler generates this code if the program uses a function pointer table... for instance, in the typical syscall routing code. Provisionally, until the bug gets fixed (I could try to do it myself...) I'm using a long switch-case block to do the syscall routing. Ugly, but works.
Having a C compiler and an assembler is not enough. The C language is just a little bit over the assembly code. It needs a library (libc) to work. I have tried to port the newlib C library to the PDP-11 target, with mixed results. The real problem is the 64K address space. The code for a simple sprintf() is larger than those 64K! I'm still working on that, but it seems the problem relies in the float/double support. Right now my "kernel" does not support floating point in any way, so I will try to get rid of the float code and see if I can put newlib on diet...

Current status

Right now my "kernel" does the following things:

  • Enables and configures memory management, so each "task" gets its 64K protected address space.
  • Creates and runs tasks in user mode, using TRAP to call the system services.
  • Multitasks, using a simple round-robbin algorithm. I plan to add priorities later.
  • Writes to console (synchronously).
  • Can provide somehow inteligible panic information when it crashes (and it does it a lot).
Right now, the "kernel" and the "tasks" are linked together. My next step will be to write a paper tape device driver, so I can move the "user tasks" out of the kernel and load them separately. Once this is done, I will work on removing the memory management to the kernel and putting it to its own task. 

I'm having a lot of fun :).



Tuesday, July 24, 2012

Writing PDP11 assembly code from Linux (and running it on bare -simulated- metal!)

Let's pretend for a moment you are as crazy as myself about computing and, specially, about classic computers like the PDP-11. Let's say your crazyness gets to the point you start to consider seriously writing your own operating system for the PDP-11. Or, at least, doing the first steps to write something similat to an operating system. Sounds scary, doesn't it? No way! It sounds fun!

Still reading? Fine, because we are going to do those very first steps towards this goal. And the very first step to build an operating system is to have the hability to write, debug and run standalone software. That is, to run programs in a PDP-11 without any operating system loaded.

To do that, we can use two different approaches:
  • We can use a running PDP11 system with an existen operating system to write and assemble the software, moving it to our "empty" system.
  • We can use a cross-assembler and cross-compiler to write the software under another operating system, and feed it to our PDP11.
At this point, it is important to remember we are talking about a simulated PDP-11. At least in my case, I don't have access to a real machine. Then, it makes sense to use the host operating environment to write and compile the software we will run in the simulator. The plan is to be able to build files loadable into the SIMH simulator using the "load" console command. Then we can use simh to run the software or to single step it. No operating system needed for that.

Load file format

Simh can load into memory files representing a paper tape image. Yup, you have read it well. Punched paper tape. Now we are talking about classic computing! 

We can find the format of those images reading the pdp11_sys.c source file of the simh distribution. The code is in a function called sim_load. The comments block of that function describes the file format, which is not very complicated. The file is composed by byte blocks, each one of them preceded by a header and followed by a checksum. The last block is en empty one (just header and checksum). The structure of the header is as follows:


Offset Length Datatype Content
0 1 char Fixed value: 1
1 1 char Fixed value: 0
2 2 word Size of the data block, in little endian format
4 2 word Load address for that block, in little endian format

The checksum is computed adding every byte value of the block including the header and taking the 2's complement of the low order byte of the result. In other words, the negative value of the low order byte taken as an unsigned character.

The last (empty) block also contains a "load address", but in this case the content of that field will be loaded into the PC register of the machine after the file has been loaded. So it has to contain the entry point for the loaded program. 

We will refer to this format as "load format".

Generating a load format file

From RT-11

The easiest way to generate a load file is to use a running RT-11 system. The RT-11 linker has the option of generating directly load files instead of native executables. We have just to add the "/LDA" switch to the LINK command and we'll get a file with a LDA extension instead of the usual SAV one. The linker will set up the file to load at the octal address 01000 by default, just over the interrupt vector area, so we will be mostly fine with the default. We can change it using the /BOTTOM switch if we really need to load our code in any other place.

So, we can edit our source code in our RT-11 system, assemble/compile it using the native MACRO-11 compiler or whatever HL language we want, and LINK the resulting object into a LDA file. Now we have to transfer that file to our host environment. We have several options to do that. As examples:
  • We can use KERMIT to move the file to our host system. For some reason, I've not been able to do this. When I launch KERMIT in SERVER mode in the RT-SYSTEM it ignores my download requests. 
  • We could use a TCP/IP stack. I haven't done that, so I can't really help about that option.
  • We can use the paper tape emulation in SIMH. To do so, we have to SYSGEN our RT-11 adding the PC device, and then we can simply COPY from or to PC: to transfer the files.
This procedure works, but you have to use the RT-11 environment and specifically the KED editor, which I've found difficult to use with my terminal emulators. You can edit in your host environment and use the paper tape device to upload your sources to RT-11, but its quite cumbersome (and you must be sure you are using the DOS convention for the line terminators...), so I wanted to find an alternative.

Cross-compiling and cross-assembling

The obvious solution is to use a cross-assembler and a cross-compiler to generate the PDP-11 code directly in your host environment. In my case, that host environment is a laptop running Ubuntu Linux. After asking in the simh mailing list, I found myself with several opti (ons:
  • The simh distribution contains a port of the "native" assembler, MACRO-11, to unix. It compiles without problems and generates PDP-11 object files. It also uses the DEC source format (being a port of the native assembler), so it seams to be the best approach to the problem. Unfortunately, an OBJ file is not loadable to SIMH, neither is enough to do medium complex things. I wanted to be able to write modular code, and to be able to link together assembly and C code. Without a linker, I couldn't do that. So I had to discard macro11. Bob Armstrong sent me an utility to extract the contents of the OBJ file to build files in EPROM HEX format; it could be extended to generate LDA files, but nevertheless the linker would still be missing.
  • The GNU toolchain. That means the gas assembler, part of the binutils package, and the very known gcc C compiler, as well as ld and the rest of utilities. After a wrong start that is the option I have choosen. Right now I have been able to write, compile and execute a "Hello world" program writing directly to the emulated PDP-11 console. So I guess I'm in the right path... Let's elaborate a little bit about how to achieve this.

Building the cross-assembler and cross-compiler

First, the bill of materials. I used these GNU packages:

That is obviously not the last gcc version, but I was not able to build the cross-compiler using the last release, so I downgraded back to 3.4. Anyway, we don't need the bleeding edge features of the last version, so we will be fine with 3.4.6. If you are going to build the cross-compiler, download just the "core" archive. Unless you want c++, fortran, ada and the rest of languages the core is all you need.

The recommended procedure to build the tools is as follows:
  • Unpackage the binutils tarball
  • Create a new directory for your binutils build, and cd to it
  • Execute the follwing command (from the new, empty directory):
<binutils_dir>/configure --target=pdp11-aout

Substitute <binutils_dir> for the directory where the tarball was expanded. This command will configure the build for a /usr/localprefix installation. You can change it if you want, using the corresponding configure options.

  • After the completion of configure, just type make to build the software and make install to move the executables to the /usr/local/bin directory (you will probably need to run that command as root using sudo or similar). You will end with a series of executables named pdp11-aout-as, pdp11-aout-ld and so on. Those executables are your cross-building tools.
  • After building binutils, you can build the cross-compiler. The procedure is basically the same, substituting binutils by gcc. It's also recommended to use a separate directory to do the build.

Using the cross-building tools

If you try to compile and link a "helloworld" program you will find the linker does not work. It will complain about a syntax error in its default linking script... 

I really had no idea about that "linker script". Well, we learn everyday. With some inspiration from this nice site, I wrote my own linking script, adapted to generate loadable PDP11 code. The script itself is this:

OUTPUT_FORMAT("a.out-pdp11")
ENTRY(start)
phys = 00001000;
SECTIONS
{
  .text phys : AT(phys) {
    code = .;
    *(.text)
    *(.rodata)
    . = ALIGN(0100);
  }
  .data : AT(phys + (data - code))
  {
    data = .;
    *(.data)
    . = ALIGN(0100);
  }
  .bss : AT(phys + (bss - code))
  {
    bss = .;
    *(.bss)
    . = ALIGN(0100);
  }
  end = .;
}
ldaout.cmd (END)                    

We are basically telling the linker we want an output format known as "a.out", and that we will be defining the three classical "C" sections (text, data and bss). The executable entry point is start, so we will have to create a global empty point in our code with that name. We are telling the linker to configure the executable to load at the address 01000 octal (0x200), and to align each section at a 0100 (octal) byte boundary.

Obviously, we are missing a detail. SIMH can't load a.out executables. The ld linker supports a binary output format, which could be easily converted to LDA just adding the header and computing the checksum, but unfortunately ld relocates the code to be loaded at the 0 memory position, and that is not useful for a PDP-11 system. So I had to write a program to convert from a.out to lda format... If you are interested you can get the sources from the git repository. It should build without any problems in any unix-like system. To use the utility to generate a LDA file from an unstructured binary type:
bin2load -f input_file -o output_file -b load_address (in octal)

To generate an LDA file from an a.out executable:
bin2load -a -f input_file -o output_file

Don't specify a load address when you convert an a.out file; that information is in the executable itself... And please take into account the utility can be improved a lot. For instance, there is no boundary checking so you could generate something which would load over the PDP-11 64K barrier. Just treat it as a toy :)

Let's play a little bit

So we have all the tools we need and it is time to give them a try. I have written a pair of very simple assembly sources. The first one is a subroutine to write a single character on the console device. It will loop until the console is ready to receive a byte, will write it and will wait again to ensure it has already been sent. Notice this source is in BSD syntax (it uses the dollar sign to specify immediate arguments).

        .TITLE putconch: send a byte to the system console
        .IDENT "V01.00"

        .GLOBAL _putconch

        XCSR    = 0177564
        XBUF    = 0177566
        TXRDY   = 0x0080
        NRETRY  = 5000

        .text

_putconch:
        mov     r1,-(sp)
        mov     r2,-(sp)
        mov     $NRETRY, r1
10$:
        mov     XCSR,r2
        bit     r2, $TXRDY
        bne     20$
        dec     r1
        bne     10$
        mov     $2,r0
        jmp     999$

20$:    movb    r0,XBUF
        mov     $NRETRY, r1
30$:    mov     XCSR,r2
        bit     r2, $TXRDY
        bne     40$
        dec     r1
        bne     30$
        mov     $2, r0
        jmp     999$

40$:    mov     $0, r0
999$:
        mov (sp)+, r2
        mov (sp)+, r1
        rts     pc

        .end _putconch                        

The second one uses this routine to write a string to the console. This one has the "start" symbol and hence is the entry point for the program:

 
     .TITLE Say hello on console
        .IDENT "V00.00"

        .GLOBAL start
        .GLOBAL _putconch

        STACK = 0x1000

        .text
start:
        mov     $STACK, sp
        mov     $hellom, r1
        mov     $helloc, r2
10$:    movb    (r1), r0
        jsr     pc, _putconch
        dec     r2
        beq     99$
        inc     r1
        jmp     10$

99$:    nop
        halt

        .data
hellom: .ascii  "Hello world!"
        helloc = . - hellom

        .end                      

To assemble the routines we will use our cross-assembler:

pdp11-aout-as putconch.s -o putconch.o
pdp11-aout-as hellopdp.s -o hellopdp.o

After that we can link the a.out executable and generate the LDA file:

pdp11-aout-ld -T ldaout.cmd hellopdp.o putconch.o -o hellopdp.out
bin2load -a -f hellopdp.out -o hellopdp.lda

And now it is the real moment:

 
sim> load hellopdp.lda
sim> e pc
PC:     001000
sim> e -m 001000:01100
1000:   MOV #10000,SP
1004:   MOV #1200,R1
1010:   MOV #14,R2
1014:   MOVB (R1),R0
1016:   JSR PC,1040
1022:   DEC R2
1024:   BEQ 1034
1026:   INC R1
1030:   JMP 1014
1034:   NOP
1036:   HALT
1040:   MOV R1,-(SP)
1042:   MOV R2,-(SP)
1044:   MOV #11610,R1
1050:   MOV 177564,R2
1054:   BIT R2,#200
1060:   BNE 1076
1062:   DEC R1
1064:   BNE 1050
1066:   MOV #2,R0
1072:   JMP 1140
1076:   MOVB R0,177566
sim> g
Hello world!
HALT instruction, PC: 001040 (MOV R1,-(SP))
sim>                                               

It worked! Not bad for such a patch work!

In the next post we will try to add some C code to the mix...

Sunday, July 15, 2012

Installing RSX-11M 4.6 from scratch - Part 3: Post-installation tasks

This is the last entry of the series depicting a full installation of the RSX-11M operating system from scratch in a simulated PDP-11 created using simh. In the previous two entries we created a baseline system from the distribution tape image and proceeded to generate the operating system itself. In this last entry we will finish the installation by:
  • Tailoring the system image.
  • Providing HELP support.
  • Creating user accounts.
  • Customizing the system startup procedure.
We begin with a pristine system, as we left it in the part 2 of this series, and we will end with a fully configured system ready to be used. However, we won't cover the installation of layered products like language processors (compilers) or decnet support (network).

Tailoring the system image

First thing we can do is to modify the system image to our convenience. In this example we will just change the terminal type for the console (TT0:) so we get a more friendly environment during the boot process. We could configure ALL the system terminals in this moment, but it is not really necessary, since we can do it in the system startup procedure.  This is a really easy thing to do, as seen in the next console log, which begins with the initial bootup of our system.

sim> b rp


  RSX-11M V4.6 BL56   124.K MAPPED

>RED DB:=SY:
>RED DB:=LB:
>MOU DB:RSXM56
>@DB:[1,2]STARTUP
>* PLEASE ENTER TIME AND DATE (HR:MN DD-MMM-YY) [S]: 13:15 15-JUL-92
>TIM 13:15 15-JUL-92
>* ENTER LINE WIDTH OF THIS TERMINAL [D D:132.]: 
>SET /BUF=TI:132.
>ACS SY:/BLKS=1024.
>;
>; This system startup command file (LB:[1,2]STARTUP.CMD) contains a
>; template of commands to initialize the queue print spooler and queue
>; LP0:, initialize the error logger, initialize the DCL CLI, and install
>; the RMS Library and Utilities.  As is these commands are commented out
>; and are not executed.  To include these commands as part of the
>; startup procedure, edit the file to remove the period and semi-colon
>; (.;) comment delimiter from the beginning of each line.  These
>; commands may be useful for initializing the various facilities for
>; your installation or else they may provide a model with which to
>; tailor initialization commands for your particular installation. 
>;

>@ <eof>
>SET /UIC=[1,54]
>RUN VMR
Enter filename: RSX11M
VMR>SET /VT100=TT0:
>^Z

At the next boot, TT0: will be treated as a VT100 so we will get proper line-editing capabilities when we enter the time and line size. It's a small improvement, but useful anyway...

Providing HELP

The system install process copies the HELP content into [1,2] in the form of a Universal Library, HELP.ULB. To get proper HELP we need to extract the contents of that library. We will be asked if we want complete (FULL) or simplified (BRIEF) help, and if we want to extract also the "introductory" files used to support the basic RSX user manual. In this installation we will ask for FULL help text and we will also get the introductory files. Back in the 70-80s, when the storage space was expensive the system managers would have analyzed the real needs of their user base and the cost of the media used to hold the files. Since we don't have those worries, we will go for the full set...

>SET /UIC=[1,2]
>INS $LBR
>LBR HELPBUILD.CMD=HELP.ULB/EX:BUILD
>@HELPBUILD
>;
>; BRIEF HELP support for MCR and/or DCL gives the command,
>; function, and syntax without extensive comments.
>;
>; FULL HELP support for MCR and/or DCL gives a full description
>; of each command element rather than just listing them.
>;
>; There is no difference between FULL and BRIEF HELP support
>; for the RSX-11M UTILITIES.
>;
>; Answer YES if you want FULL HELP support for MCR and all
>; the UTILITIES.
>;
>* Do you want FULL HELP support for MCR? [Y/N]: Y
>;
>; Answer YES if you want FULL HELP support for DCL and all
>; the UTILITIES. 
>;
>* Do you want FULL HELP support for DCL? [Y/N]: Y
>;
>; Answer YES if you want the INTRODUCTORY files used with the manual 
>; 'INTRODuction to RSX-11M'.  This manual includes a full interactive
>; terminal session.  These files are used with that session.  See the
>; section on help files in the Post-System-Generation Guidelines
>; Chapter of the RSX-11M System Generation and Installation Guide for
>; more information.
>;
>* Do you want the INTRODUCTORY FILES? [Y/N]: Y
>;
>; The following options have been selected:
>;
>;  FULL HELP SUPPORT FOR MCR
>; FULL HELP SUPPORT FOR DCL
>; INTRODUCTORY FILES
>;
>; The appropriate files will now be extracted from the
>; HELP Universal Library.
>;
>LBR MCRFULL.CMD=HELP.ULB/EX:MCRFUL
>;
>; This file extracts all the files that are necessary when full MCR
>; help is chosen.
>;
>LBR HELPF.HLP=HELP.ULB/EX:HELPF
>LBR MCR.HLP=HELP.ULB/EX:MCR
>LBR MCRACT.HLP=HELP.ULB/EX:ACT
>LBR MCRALT.HLP=HELP.ULB/EX:ALT
>LBR MCRASN.HLP=HELP.ULB/EX:ASN
>LBR MCRATL.HLP=HELP.ULB/EX:ATL
>LBR MCRBRO.HLP=HELP.ULB/EX:BRO
>LBR MCRCLI.HLP=HELP.ULB/EX:CLI
>LBR MCRFLA.HLP=HELP.ULB/EX:FLA
>LBR MCRGENRL.HLP=HELP.ULB/EX:GENRL
>LBR MCRHELO.HLP=HELP.ULB/EX:HELO
>LBR MCRHELP.HLP=HELP.ULB/EX:MHELP
>LBR MCRHOM.HLP=HELP.ULB/EX:HOM
>LBR MCRINI.HLP=HELP.ULB/EX:INI
>LBR MCRINS.HLP=HELP.ULB/EX:INS
>LBR MCRLOA.HLP=HELP.ULB/EX:LOA
>LBR MCRLOGIN.HLP=HELP.ULB/EX:MLOGIN
>LBR MCRMOU.HLP=HELP.ULB/EX:MOU
>LBR MCROPE.HLP=HELP.ULB/EX:OPE
>LBR MCRRUN.HLP=HELP.ULB/EX:MRUN
>LBR MCRSAV.HLP=HELP.ULB/EX:SAV
>LBR MCRSET.HLP=HELP.ULB/EX:SET
>LBR MCRTAS.HLP=HELP.ULB/EX:TA
>LBR MCRUFD.HLP=HELP.ULB/EX:UFD
>LBR DCLFULL.CMD=HELP.ULB/EX:DCLFUL
>;
>; This file extracts all the files that are necessary when full DCL
>;  help is chosen.
>;
>LBR DCL.HLP=HELP.ULB/EX:DCL
>LBR DCLABORT.HLP=HELP.ULB/EX:ABORT
>LBR DCLALLOC.HLP=HELP.ULB/EX:ALLOC
>LBR DCLANALYZ.HLP=HELP.ULB/EX:ANALYZ
>LBR DCLANALER.HLP=HELP.ULB/EX:ANALER
>LBR DCLANALCD.HLP=HELP.ULB/EX:ANALCD
>LBR DCLAPPEND.HLP=HELP.ULB/EX:APPEND
>LBR DCLASSIGN.HLP=HELP.ULB/EX:ASSIGN
>LBR DCLASSQ.HLP=HELP.ULB/EX:ASSQ
>LBR DCLBACKUP.HLP=HELP.ULB/EX:BACKUP
>LBR DCLBASIC.HLP=HELP.ULB/EX:DBASIC
>LBR DCLBRO.HLP=HELP.ULB/EX:DCLBRO
>LBR DCLC81.HLP=HELP.ULB/EX:DCLC81
>LBR DCLCANCEL.HLP=HELP.ULB/EX:CANCEL
>LBR DCLCOBOL.HLP=HELP.ULB/EX:DCOBOL
>LBR DCLCONT.HLP=HELP.ULB/EX:CONT
>LBR DCLCONV.HLP=HELP.ULB/EX:CONV
>LBR DCLCOPY.HLP=HELP.ULB/EX:COPY
>LBR DCLCORAL.HLP=HELP.ULB/EX:DCORAL
>LBR DCLCREATE.HLP=HELP.ULB/EX:CREATE
>LBR DCLDEASS.HLP=HELP.ULB/EX:DEASS
>LBR DCLDEASSQ.HLP=HELP.ULB/EX:DEASSQ
>LBR DCLDELETE.HLP=HELP.ULB/EX:DELETE
>LBR DCLDELJ.HLP=HELP.ULB/EX:DELJ
>LBR DCLDELQ.HLP=HELP.ULB/EX:DELQ
>LBR DCLDIFF.HLP=HELP.ULB/EX:DIFF
>LBR DCLDIR.HLP=HELP.ULB/EX:DIR
>LBR DCLDIS.HLP=HELP.ULB/EX:DIS
>LBR DCLEDIT.HLP=HELP.ULB/EX:EDIT
>LBR DCLEDT.HLP=HELP.ULB/EX:DEDT
>LBR DCLFIX.HLP=HELP.ULB/EX:FIX
>LBR DCLFORT.HLP=HELP.ULB/EX:FORT
>LBR DCLHELP.HLP=HELP.ULB/EX:DHELP
>LBR DCLHOLD.HLP=HELP.ULB/EX:HOLD
>LBR DCLINIT.HLP=HELP.ULB/EX:INIT
>LBR DCLINST.HLP=HELP.ULB/EX:INST
>LBR DCLLIB.HLP=HELP.ULB/EX:LIB
>LBR DCLLINK.HLP=HELP.ULB/EX:LINK
>LBR DCLLOGIN.HLP=HELP.ULB/EX:LOGIN
>LBR DCLLOGOUT.HLP=HELP.ULB/EX:LOGOUT
>LBR DCLMACRO.HLP=HELP.ULB/EX:MACRO
>LBR DCLMCR.HLP=HELP.ULB/EX:DCLMCR
>LBR DCLMOUNT.HLP=HELP.ULB/EX:MOUNT
>LBR DCLPRINT.HLP=HELP.ULB/EX:DPRIT
>LBR DCLPURGE.HLP=HELP.ULB/EX:PURGE
>LBR DCLREL.HLP=HELP.ULB/EX:REL
>LBR DCLREMOVE.HLP=HELP.ULB/EX:REMOVE
>LBR DCLRENAME.HLP=HELP.ULB/EX:RENAME
>LBR DCLREQ.HLP=HELP.ULB/EX:REQ
>LBR DCLRES.HLP=HELP.ULB/EX:DCLRES
>LBR DCLRUN.HLP=HELP.ULB/EX:DRUN
>LBR DCLSET.HLP=HELP.ULB/EX:DSET
>LBR DCLSETQ.HLP=HELP.ULB/EX:SETQ
>LBR DCLSHORTS.HLP=HELP.ULB/EX:SHORTS
>LBR DCLSHOW.HLP=HELP.ULB/EX:SHOW
>LBR DCLSHOWP.HLP=HELP.ULB/EX:SHOWP
>LBR DCLSHOWQ.HLP=HELP.ULB/EX:SHOWQ
>LBR DCLSTART.HLP=HELP.ULB/EX:START
>LBR DCLSTOP.HLP=HELP.ULB/EX:STOP
>LBR DCLTYPE.HLP=HELP.ULB/EX:TYPE
>LBR DCLUNFIX.HLP=HELP.ULB/EX:UNFIX
>LBR UTIL.CMD=HELP.ULB/EX:UTIL
>;
>; This file contains commands to extract all the utility files
>; from HELP.ULB.  These files are extracted if any form of HELP
>; is requested (i.e. full MCR or DCL, or brief MCR or DCL).
>;
>LBR ASCII.HLP=HELP.ULB/EX:ASCII
>LBR BAD.HLP=HELP.ULB/EX:BAD
>LBR BRU.HLP=HELP.ULB/EX:BRU
>LBR CDA.HLP=HELP.ULB/EX:CDA
>LBR CMP.HLP=HELP.ULB/EX:CMP
>LBR COT.HLP=HELP.ULB/EX:COT
>LBR DMP.HLP=HELP.ULB/EX:DMP
>LBR DSC.HLP=HELP.ULB/EX:DSC
>LBR EDI.HLP=HELP.ULB/EX:EDI
>LBR EDTHELP.HLP=HELP.ULB/EX:EDTHLP
>LBR ERROR.HLP=HELP.ULB/EX:ERROR
>LBR EXECUTIVE.HLP=HELP.ULB/EX:EXEC
>LBR FCS.HLP=HELP.ULB/EX:FCS
>LBR FLX.HLP=HELP.ULB/EX:FLX
>LBR FMT.HLP=HELP.ULB/EX:FMT
>LBR ICP.HLP=HELP.ULB/EX:ICP
>LBR IOX.HLP=HELP.ULB/EX:IOX
>LBR LBR.HLP=HELP.ULB/EX:LBR
>LBR MAG.HLP=HELP.ULB/EX:MAG
>LBR MERGE.HLP=HELP.ULB/EX:MERGE
>LBR ODT.HLP=HELP.ULB/EX:ODT
>LBR PAT.HLP=HELP.ULB/EX:PAT
>LBR PIP.HLP=HELP.ULB/EX:PIP
>LBR PMD.HLP=HELP.ULB/EX:PMD
>LBR SLP.HLP=HELP.ULB/EX:SLP
>LBR SORT.HLP=HELP.ULB/EX:SORT
>LBR SYSGEN.HLP=HELP.ULB/EX:SYSGEN
>LBR SYSLIB.HLP=HELP.ULB/EX:SYSLIB
>LBR TKB.HLP=HELP.ULB/EX:TKB
>LBR TDX.HLP=HELP.ULB/EX:TDX
>LBR TKBOPT.HLP=HELP.ULB/EX:TKBOPT
>LBR TKTN.HLP=HELP.ULB/EX:TKTN
>LBR VFY.HLP=HELP.ULB/EX:VFY
>LBR VMR.HLP=HELP.ULB/EX:VMR
>LBR ZAP.HLP=HELP.ULB/EX:ZAP
>LBR RMS.HLP=HELP.ULB/EX:RMS
>LBR RMSBCK.HLP=HELP.ULB/EX:RMSBCK
>LBR RMSCNV.HLP=HELP.ULB/EX:RMSCNV
>LBR RMSDEF.HLP=HELP.ULB/EX:RMSDEF
>LBR RMSDES.HLP=HELP.ULB/EX:RMSDES
>LBR RMSDSP.HLP=HELP.ULB/EX:RMSDSP
>LBR RMSIFL.HLP=HELP.ULB/EX:RMSIFL
>LBR RMSRST.HLP=HELP.ULB/EX:RMSRST
>LBR MCRUTIL.CMD=HELP.ULB/EX:MCRUTL
>;
>; This file extracts all the files required when either MCR brief
>; or full help was chosen.
>;
>LBR BAS.HLP=HELP.ULB/EX:BAS
>LBR MCRCCC.HLP=HELP.ULB/EX:MCRCCC
>LBR MCRCORAL.HLP=HELP.ULB/EX:MCORAL
>LBR MCREDT.HLP=HELP.ULB/EX:MCREDT
>LBR MCRFORT.HLP=HELP.ULB/EX:MFORT
>LBR MCRMAC.HLP=HELP.ULB/EX:MCRMAC
>LBR MCRPRINT.HLP=HELP.ULB/EX:MPRINT>LBR MCRQUE.HLP=HELP.ULB/EX:MCRQUE
>LBR MCRPASCAL.HLP=HELP.ULB/EX:MPASCL
>LBR DCLUTIL.CMD=HELP.ULB/EX:DCLUTL
>;
>; This is a command file to extract any files that go with either
>; full or brief DCL help.
>;
>LBR DCLCCC.HLP=HELP.ULB/EX:DCLCCC
>LBR DCLPASCAL.HLP=HELP.ULB/EX:DPASCL
>LBR INTRO.ULB=HELP.ULB/EX:INTRO
>LBR INTROFIL.CMD=INTRO.ULB/EX:INTROF
>@<EOF>

Right now we have full HELP support, both for MCR and DCL.

Creating user accounts

If we want to use our RSX system in multiuse mode must create the accounts file and define some user accounts. We will define a SYSTEM account, bound to the [1,2] UIC, and a USER account, bound to [200,1]. Additionally, we will provide the USER account with the introductory files extracted from the help universal library. We will create those accounts with no password... Of course this is not a good idea if you want to share your system with someone else...

Creating the accounts file

To create and manage the accounts file we must use the ACNT program, located in the [1,54] UIC. The first step is to create the accounts file itself using the "C" command. This is the corresponding console log:

>SET /UIC=[1,54]

>RUN ACNT
 * ACCOUNT FILE MAINTENANCE PROGRAM *


Options are: A - ADD, C - CREATE FILE, D - DELETE, E - EXAMINE,
L - LIST, M - MODIFY, S - SORT,  CTRL/Z - EXIT

Enter option: C

Enter maximum number of accounts: 25

Options are: A - ADD, C - CREATE FILE, D - DELETE, E - EXAMINE,
L - LIST, M - MODIFY, S - SORT,  CTRL/Z - EXIT

Enter option:

Creating the SYSTEM and USER accounts

Now we can create our two initial accounts.

Enter option: A
Enter account or  for options ( N,N ): 1,2
Password ( <=6 chars. ): 
Default system device ( DDU ): DB0
First name ( <=12 chars. ): 
Last name ( <=14 chars. ): SYSTEM
Enter user CLI (default=MCR): 
Slave terminal? [Y/N]: 
UFD DB00:[001,002]
UFD -- Directory already exists

>

Enter account or  for options ( N,N ): 200,1
Password ( <=6 chars. ): 
Default system device ( DDU ): DB0
First name ( <=12 chars. ): 
Last name ( <=14 chars. ): USER
Enter user CLI (default=MCR): 
Slave terminal? [Y/N]: 
UFD DB00:[200,001]


UFD -- Directory already exists

>
Enter account or  for options ( N,N ): <ESC>

Options are: A - ADD, C - CREATE FILE, D - DELETE, E - EXAMINE,
L - LIST, M - MODIFY, S - SORT,  CTRL/Z - EXIT

Enter option: ^Z

Operation complete


Copying the introductory files to the USER account

Once we have created the accounts and exited the ACNT program, we can provide the introductory files to the user account.

>SET /UIC=[200,1]

>PIP /NV=[1,2]INTRO.ULB,INTROFIL.CMD
>@INTROFIL
>LBR CLEAN.CMD=INTRO.ULB/EX:CLEAN
>LBR CLKGEN.CMD=INTRO.ULB/EX:CLKGEN
>LBR DELETE.CMD=INTRO.ULB/EX:DELETE
>LBR LOGIN.CMD=INTRO.ULB/EX:LOGIN
>LBR MYDISK.CMD=INTRO.ULB/EX:MYDISK
>LBR SHAVE.CMD=INTRO.ULB/EX:SHAVE
>LBR SHOW.CMD=INTRO.ULB/EX:SHOW
>LBR CLOCK.MAC=INTRO.ULB/EX:CLOCK
>LBR HIYA.MAC=INTRO.ULB/EX:HIYA
>LBR STARS.MAC=INTRO.ULB/EX:STARS
>LBR TMCLI.MAC=INTRO.ULB/EX:TMCLI
>LBR TMCLI.FTN=INTRO.ULB/EX:TMCLI1
>LBR ERROR.TSK=INTRO.ULB/EX:ERROR1
>LBR SEVERE.TSK=INTRO.ULB/EX:SEVERE
>LBR SUCCESS.TSK=INTRO.ULB/EX:SUCESS
>LBR WARNING.TSK=INTRO.ULB/EX:WARNING
>LBR FLU.TXT=INTRO.ULB/EX:FLU
>LBR FLY.TXT;1=INTRO.ULB/EX:FLY1
>LBR FLY.TXT;2=INTRO.ULB/EX:FLY2
>LBR FLY.TXT;3=INTRO.ULB/EX:FLY3
>LBR HELLO.TXT=INTRO.ULB/EX:HELLO
>LBR LONG.TXT=INTRO.ULB/EX:LONG
>LBR WHATSHERE.TXT=INTRO.ULB/EX:WHATS
>@ 


And that's it. We have now two accounts, a privileged one and a user, nonprivileged one.


Customizing the system startup procedure
The system startup procedure, STARTUP.CMD, is located in the [1,2] directory. The installation provides us with a template we can modify to our preference. This is the one I'm using as a starting point. The lines I added or modified are highlighted in bold.

.ENABLE SUBSTITUTION
.SETS   RK05    "DK"
.SETS   RL01    "DL"
.ASKS TIM PLEASE ENTER TIME AND DATE (HR:MN DD-MMM-YY)
TIM 'TIM'
.ASKN [::132.] N ENTER LINE WIDTH OF THIS TERMINAL
SET /BUF=TI:'N'.
.IF RK05 EQ "'<sydisk>'" .GOTO END
.IF RL01 NE "'<sydisk>'" .GOTO BIG
.IFINS ...ACS  ACS SY:/BLKS=512.
.GOTO END
.BIG:
.IFINS ...ACS  ACS SY:/BLKS=1024.
.END:
.IFT <baslin> .GOTO 50
.IFNINS QUE .IFNINS ELI .IFNINS DCL .GOTO 50
;
; This system startup command file (LB:[1,2]STARTUP.CMD) contains a
; template of commands to initialize the queue print spooler and queue
; LP0:, initialize the error logger, initialize the DCL CLI, and install
; the RMS Library and Utilities.  As is these commands are commented out
; and are not executed.  To include these commands as part of the
; startup procedure, edit the file to remove the period and semi-colon
; (.;) comment delimiter from the beginning of each line.  These
; commands may be useful for initializing the various facilities for
; your installation or else they may provide a model with which to
; tailor initialization commands for your particular installation.
;
.50:
.;      ;
.;      ; INITIALIZE THE QUEUE PRINT SPOOLER
.;      ;
.;      ; START THE QUEUE MANAGER
        QUE /START:QMG
.;      ; QUEUE LP0:
        QUE LP0:/CR/NM
        QUE LP0:/SPOOL/FLAG:1
        QUE LP0:/ASSIGN:PRINT
.;      ;
.;      ; INITIALIZE THE ERRORLOGER
.;
        ELI /LOG
.;      ;
.;      ; INITIALIZE DCL
.;      ;
        CLI /INIT=DCL/TASK=...DCL
.;      ;
.;      ;
.;      ; INSTALL RMS LIBRARIES  AND UTILITIES
.;      ;
.;      ; NOTE - These examples use the top of the GEN partition to create an
.;      ; appropriate sized partition.  You must replace "base" in each of the
.;      ; examples below with the octal address of the base of the new
.;      ; partition.
.;      ;
.;      ; If you wish to use the full-function RMS resident library,
.;      ; use the following commands:
.;      ;
.;              SET /TOP=GEN:-1300
.;              SET /MAIN=RMSRES:36531:1300:COM
.;              INS LB:[1,1]RMSRES.TSK
.;      ;
.;      ; If you wish to use the subset RMS resident library, use the
.;      ; following commands:
.;
.;              SET /TOP=GEN:-600
.;              SET /MAIN=RMSRES:base:600:COM
.;              INS LB:[1,1]RMSRESSUB.TSK
.;      ;
.;      ; If you wish to use the RMSDAP resident library to access RMS files
.;      ;on remote nodes, create a partition and install the following library:
.;
.;              SET /TOP=GEN:-500
.;              SET /MAIN=DAPRES:base:500:COM
.;              INS LB:[1,1]DAPRES.TSK
.;      ;
.;      ;The following RMS utilities may be individually installed as needed:
.;      ;
.;      INS LB:[1,54]RMSDES.TSK
.;      INS LB:[1,54]RMSDEF.TSK
.;      INS LB:[1,54]RMSBCK.TSK
.;      INS LB:[1,54]RMSRST.TSK
.;      INS LB:[1,54]RMSCNV.TSK
.;      INS LB:[1,54]RMSIFL.TSK
.;      INS LB:[1,54]RMSDSP.TSK

        INS LB:[1,54]PIP.TSK
        INS LB:[1,54]EDT.TSK
        INS LB:[1,54]TKB.TSK
        SET /VT100=TT1:
        SET /VT100=TT2:
        SET /VT100=TT3:
        SET /VT100=TT4:
        SET /VT100=TT5:
        SET /VT100=TT6:
        SET /VT100=TT7:
        SET /VT100=TT10:

As you can see, the changes I made were:

  • Enabling the printer spooled.
  • Enablig the error logger.
  • Installing and enabling the DCL command processor.
  • Installing some images I guess I would use: the EDT editor, the PIP utility and the task builder.
  • Configuring the DZ11 lines for a VT100 emulated terminal.

 And that's all! At this moment you should take another backup of your system disk image, and then you could begin installing layered products. If you search the internet, remember most of the tapes in trailing-edge.com are corruptes (not everyone, but most of them). I've found that BP2 2.5 is usable. With a little bit of luck you can find other kits in other sites (to be honest, I can't even remember where did I get mine...). I plan to make more posts about the PDP11 and RSX, and I'll try to publish the installation logs for the layereds I've been able to get. But this will be another post...

Thursday, July 12, 2012

Installing RSX-11M 4.6 from scratch - Part 2: System generation (SYSGEN)

SYSGEN process

We ended the first post of this series with a bootable baseline system. This is a generic system, which has to be tailored to our desired configuration. This process is named SYSGEN (system generation) and consists of three steps or phases. The phases 1 and 2 can be chained together, while the phase 3 has to be executed manually. At the end of SYSGEN we will have a RSX11M system tailored to our hardware configuration and ready to boot.

SYSGEN can also be used to customize the executive ("kernel") characteristics, and to select which features we want to have generated. In this example we will NOT do that kind of advanced configuration. We will choose the "standard function" configuration, which will build a quite complete system. We will also select the option to support DECNET-11 just in case we want/can install it in the future.

SYSGEN phase 1 and 2

The console log that follows corresponds to the preparation and execution of the first two phases of SYSGEN. As before, the user input is highlighted in bold and the log has been minimally edited to improve readability.

As you will see, this SYSGEN run used the autoconfig facility to find out the CSR and interrupt vectors for the configured devices. Take into account that ACF is not always available. For instance, if you SYSGEN from an online system you will have to enter that information by hand. The SIMH show config command will tell you the necessary information... if you are using a simulated system!

Notice: Please take into account the warning note about questions 53 and 54. I found that mistake after publishing this log. I plan to do a new log and replace this one for a corrected one, but in the interim, please, please, don't use DB0: as your CDA device!


sim> boot rp

  RSX-11M V4.6 BL56   124.K MAPPED (BASELINE)

>RED DB:=SY:
>RED DB:=LB:
>MOU DB:RSXM56
>@DB:[1,2]STARTUP
>* PLEASE ENTER TIME AND DATE (HR:MN DD-MMM-YY) [S]: 10:27 12-jul-92
>TIM 10:27 12-jul-92

>* ENTER LINE WIDTH OF THIS TERMINAL [D D:132.]: 
>SET /BUF=TI:132.
>ACS SY:/BLKS=1024.
>@ <eof>
>
>set /uic=[200,200]
>@SYSGEN
>;
>; RSX-11M V4.6 BL56   System Generation PHASE I -- Version 04.17
>
>; 12-JUL-92 10:27:16
>; Big disk distribution kit
>;

>*  1. Autoconfigure the host system hardware? [Y/N]: y
>INS $ACF.BSL
>INS $ACO
>ACF
>ACO SHOW
Processor Type:  11/45          Memory Size:  124. Kw

Options:

        Floating Point Processor (FP11)
        Extended Instruction Set (EIS)
        Switch Register (SWR)
        Display Register
        Parity Memory

Name    Vector     CSR      Unit    Type      Remark
DLA      160      174400                     
                             0      RL02     
                             1      RL02     
                             2      RL01     
                             3      RL01     
RHA      254      176700                      Mixed Massbus devices
                             0      RP06     
                             1      RP06     
                             2      RM03     
                             3      RM03     
                             4      RM03     
                             5      RM03     
                             6      RM03     
                             7      RM03     
MSA      224      172522                     
LPA      200      177514                     
PRA      070      177550                     
PPA      074      177554                     
YLA      060      177560                     
YZA      300      160100                     

>ACO SYSGEN
>REM ACF
>REM ACO
>*  2. Do you want to override Autoconfigure results? [Y/N]: 
>*  3. Do you want to inhibit execution of MCR commands (PREPGEN)? [Y/N]: 
>INS $PIP
>INS $UFD
>INS $EDI
>INS $LBR
>INS $INI
>INS $MAC
>*  4. Have you made a copy of the distribution kit? [Y/N]: y
>*  5. Are you generating an unmapped system? [Y/N]: n
>*  6. Use an input saved answer file? [Y/N]: n
>*  8. Do you want a Standard Function System? [Y/N]: y
>;
>; Standard Function System - Phase I SYSGEN
>;
>*  9. Name of output saved answer file [D: SYSSAVED.CMD] [S]: 
>;
>; Phase I output saved answers created in file DB0:[200,200]SYSSAVED.CMD;1
>;
>* 14. Clean up files from previous GENs? [Y/N]: y
>* 15. Chain to Phase II after Phase I completes? [Y/N]: y
>SET /UIC=[1,1]
>PIP [1,20]RSXBLD.CMD;*/DE/NM
>PIP [1,24]RSXBLD.CMD;*/DE/NM,TTDRVBLD;*
>PIP [1,50]SYSVMR.CMD;*/DE/NM,[1,54]SYSVMR;*
>PIP [11,20]*.OBJ;*/DE/NM,*.UDC;*,*.ICR;*,*.IDS;*,*.PCS;*
>PIP [11,24]*.OBJ;*/DE/NM,*.UDC;*,*.ICR;*,*.IDS;*,*.TTY;*,*.PCS;*
>PIP [11,30]*.LST;*/DE/NM,[11,34]*.LST;*
>PIP [11,10]RSXMC.MAC;*/DE/NM,ICTAB;*,[200,200]SGNPARM.CMD;*
>PIP [200,200]RSXBLD.CMD;*/DE/NM,TTDRVBLD;*
>PIP SY:[11,20]RSXASM.CMD;*/DE/NM,RSXDRVASM;*,[12,20]MCRSETASM;*
>PIP SY:[11,24]RSXASM.CMD;*/DE/NM,RSXDRVASM;*,[12,20]MCRSETASM;*
>PIP SY0:[11,24]RSXASM.CMD;*/DE/NM,RSXDRVASM;*,[12,24]MCRSETASM;*
>PIP /FR

DB0: has 300552. blocks free, 40118. blocks used out of 340670.
Largest contiguous space = 164956. blocks
9459. file headers are free, 1108. headers used out of 10567.

>SET /UIC=[11,10]
>;
>; Target configuration
>;
>* 10. Line frequency:   A- 60 Hz    B- 50 Hz   [D: A] [S]: 
>;
>; The response to the following question specifies the highest interrupt
>; vector.  If you respond with a value less than or equal to 400, SYSGEN
>; will assign the value associated with the highest interrupt vector
>; specified during the Peripheral Section.  Therefore, if your system
>; will include devices that are not specified during the Peripheral
>; Section and which have vectors above 400 (devices such as K-series and
>; certain communication devices), specify that value in the next question.
>;
>* 14. Highest interrupt vector [O R:0-774 D:0]: 
>;     For device configuration: "*" Prints device table, "." Terminates inquiry
>;                               "?" Prints current configuration
>;     Enter devices and number of controllers for devices which require drivers
>;
>;     Current system configuration:
>;
>;     DB=1, DL=1, LP=1, MS=1, NL=1, PP=1, PR=1, CO=1
>;     YL=1, YZ=1
>* 15. Devices [S]: .
>;
>; Processor:11/45   Memory Size:124K,Mapped   System:RSX-11M
>;
>;           Switch Register
>;           Floating Point Processor
>;           Extended Instruction Set
>;           Parity Memory
>;
>; Host configuration
>;
>*  1. Is a line printer available? [Y/N]: n
>*  3. Does the listing/map device have at least 120 columns? [Y/N]: 
>*  4. Assembly listings device (ddu:) [D: "NL:"] [S]: 
>*  5. Map device for Executive and device drivers (ddu:) [D: SY0:] [S]: 
>;
>; Executive Options
>;
>;     Cancel selective marktime support will be included
>;
>;     Answer Y(ES) if the following support is desired
>;
>* 30. Executive Debugging Tool (XDT)? [Y/N]: 
>* 32. Include support for communications products (such as DECnet)? [Y/N]: y
>;
>;  If you will be generating DECnet into this system, be sure you have
>;  read the section on SYSGEN requirements in the  "RSX DECnet Network
>;  Generation and Installation Guide." 
>;  Several  DECnet  features  (eg. remote terminal support,  11S  task 
>;  loading/upline dumping, etc.) require special  consideration during
>;  SYSGEN.
>;
>* 32A. Include Network Command Terminal support? [Y/N]: y
>;     Checkpointing support will be included

WARNING: The answers to the questions 53 and 54 are WRONG. Terribly wrong. DON'T USE YOUR SYSTEM DISK AS THE CDA DEVICE! If the system crashes the dump will render yout disk unbootable! Use whatever else device you have configured. A tape device like MS0: can be a good option. Answer MS0: to the question number 53, and you will get reasonable defaults for the CSR in question 54.

sim> boot rp
>* 53. Enter CDA memory dump device mnemonic (ddu:) [S R:3-4]: db0:
>* 54. Enter CDA memory dump device CSR [O R:160000-177700 D:176700]: 
>* 56. RT-11 emulation support? [Y/N]: 
>;
>;
>; Terminal driver options
>;      The Full Duplex Terminal Driver will be included.
>;
>; System Options
>;
>;
>;     Answer Y(ES) if the following support is desired
>;
>* 2A. Include support for the IP11 Industrial I/O Subsystem? [Y/N]: n
>* 11. What name would you like to give your system [D: RSX11M] [S R:0-6]: 
>* 12. Do you want SPM-11 support? [Y/N]: 
>;
>;     Thinking ...
>; End of Executive option generation at 10:28:24 on 12-JUL-92
>;
>; Peripheral configuration
>;
>;     Parameters  appearing  in  square  brackets  "[...]"  can  only be
>;     specified  for  the  first  controller  of  a  particular  device.
>;     Parameters appearing in parentheses "(...)" only need be specified
>;     if   the  indicated  option  is  present  on  the  target  system.
>;    
>;     The   default  for  loadable  drivers  has  been  set  to  *TRUE*.
>;     To override this setting enter R (resident) as the first parameter
>;     for    the    first    controller   of   the   specified   device.
>;    
>; A/D and Laboratory devices: None specified
>;
>; Interprocessor communication devices: None specified
>;
>; Unit record devices: LP, PR, PP
>;
>; Disks: DB, DL
>;
>; Tapes: MS
>;
>; Non-physical (pseudo) devices: CO, NL, TI, CL, LB, SY
>;
>; Terminal interface devices: YL, YZ
>;
>SET /UIC=[1,24] ! Creating TTDRVBLD.CMD
>SET /UIC=[11,10]
>; End of interrupt vector area has been set to 400
>;
>;
>; Create Executive build files
>;
>PIP RSXMC.MAC=SY0:RSXMC0.MAC/AP
>ASN SY:=LB:
>;
>; Start of Executive assembly at 10:28:31 on 12-JUL-92
>SET /UIC=[11,24]
>MAC @SY:RSXASM
>;
>; End of Executive assembly at 10:29:26 on 12-JUL-92
>;
>; Start of MCR (subset) assembly at 10:29:26 on 12-JUL-92
>SET /UIC=[12,24]
>PIP *.OBJ;*/DE/NM
>MAC @SY:MCRSETASM
>;
>; End of MCR (subset) assembly at 10:29:43 on 12-JUL-92
>;
>;
>; Start of device drivers assembly at 10:29:43 on 12-JUL-92
>SET /UIC=[11,24]
>MAC @SY:RSXDRVASM
>;
>; End of device drivers assembly at 10:30:34 on 12-JUL-92
>ASN =LB:
>;
>; Prepare for task building
>;
>SET /UIC=[1,24]
>PIP RSX11M.OBS=[11,24]*.OBJ
>PIP TTDRV.OBJ=[11,24]*.TTY
>LBR RSX11M/CR:100.:1010.:128./-EP=RSX11M.OBS
>LBR TTDRV/CR:30.:380.:64.=TTDRV
>PIP [1,24]MCR.OBJ/NV/NM=[12,24]*.OBJ
>PIP [12,24]*.OBJ;*/DE/NM
>PIP /NV=[11,10]RSXBLD.CMD
>PIP [11,10]RSXBLD.CMD;*/DE/NM
>REM LBR
>;
>; Clean-up extraneous object files
>;
>PIP RSX11M.OBS;*/DE/NM,TTDRV.OBJ;*,[11,24]*.OBJ;*,*.TTY;*
>REM MAC
>REM UFD
>REM INI
>REM PIP
>REM EDI
>;
>;  End of SYSGEN phase I at 10:30:37 on 12-JUL-92
>;      -- Chaining to [200,200]SYSGEN2.CMD
>;
>SET /UIC=[200,200]
>;
>; RSX-11M V4.6 BL56  System Generation PHASE II -- Version 3.02
>;
>; 12-JUL-92 10:30:37
>;
>;
>; Big disk distribution kit SYSGEN version 04.17 for RSX-11M BL56  
>;
>; Continuation from SYSGEN PHASE I done on 12-JUL-92 at 10:30:37
>;
>; SYSGEN assumes that the map disk is already mounted in SY0: with
>; UFD [1,34].
>;
>;
>INS $PIP
>INS $EDI
>INS $LBR
>INS SY:[1,54]TKB.TSK/TASK=...TKL
>;
>; Standard Function System - Phase II SYSGEN
>;
>;
>; Phase II output saved answers created in file DB0:[200,200]SYSSAVED.CMD;1
>;
>ASN SY:=LB:
>PIP /FR

DB0: has 300182. blocks free, 40488. blocks used out of 340670.
Largest contiguous space = 164956. blocks
9448. file headers are free, 1119. headers used out of 10567.

>;
>; Start of library build at 10:30:38 on 12-JUL-92
>;
>SET /UIC=[1,1]
>PIP LB:ANSLIB.OLB/NV=LB:SYSLIB.OLB
>LBR LB:ANSLIB/RP=SY0:FCSMTA
Module "ANSPAD" replaced
Module "ASSLUN" replaced
Module "BIGBUF" replaced
Module "CLOSE " replaced
Module "CONTRL" replaced
Module "CREATE" replaced
Module "DIRECT" replaced
Module "FCSTYP" replaced
Module "GET   " replaced
Module "GETSQ " replaced
Module "OPEN  " replaced
Module "OPENR " replaced
Module "OPFID " replaced
Module "OPFNB " replaced
Module "PARSFN" replaced
Module "POINT " replaced
Module "PUT   " replaced
Module "PUTSQ " replaced
Module "RDWAIT" replaced
Module "RETADR" replaced
Module "RSTFDB" replaced
Module "RWBLK " replaced
Module "RWLONG" replaced
Module "WATSET" replaced
Module "WTWAIT" replaced
Module "WTWATD" replaced

>SET /UIC=[1,24]
>LBR SY0:MCR/RP=SY0:MCR.OBJ
Module "DV2OV " replaced
Module "SPSOV " replaced
Module "STSUB " replaced
Module "SX1OV " replaced
Module "SX2OV " replaced
Module "SX3OV " replaced
Module "SX4OV " replaced
Module "ST5OV " replaced
>;
>; End of library build at 10:30:43 on 12-JUL-92
>;
>;
>; Start of Executive task build at 10:30:43 on 12-JUL-92
>;
>PIP [1,34]*.*;*/DE/NM
>TKL @LB:RSXBLD
>;
>; End of Executive task build at 10:30:47 on 12-JUL-92
>;
>;
>; Start of system image creation at 10:30:47 on 12-JUL-92
>;
>SET /UIC=[1,54]
>PIP RSX11M.SYS/CO/NV/BL:498.=RSX11M.TSK
>;
>; End of system image creation at 10:30:47 on 12-JUL-92
>;
>;
>; Start of full duplex terminal driver task build at 10:30:47 on 12-JUL-92
>;
>SET /UIC=[1,24]
>TKL @LB:TTDRVBLD
>;
>; End of full duplex terminal driver task build at 10:30:49 on 12-JUL-92
>;
>;
>; Start of loadable driver task build at 10:30:49 on 12-JUL-92
>;
>TKL @SY0:CODRVBLD
>TKL @SY0:DBDRVBLD
>TKL @SY0:DLDRVBLD
>TKL @SY0:LPDRVBLD
>TKL @SY0:MSDRVBLD
>TKL @SY0:PPDRVBLD
>TKL @SY0:PRDRVBLD
>;
>; End of loadable driver task build at 10:30:51 on 12-JUL-92
>;
>;
>; Start of common block task build at 10:30:51 on 12-JUL-92
>;
>; Build the ANSLIB flavor of the FCS resident library common
>;
>;
>; SYSGEN assumes that the map disk is mounted in SY0: 
>; and that UFD [1,34] exists on it.
>;
>;
>; Creating the task build .CMD and .ODL files in SY:[1,24]
>;
>TKL @SY:[1,24]FCSRS1BLD.CMD
>;
>; End of common block task build at 10:30:53 on 12-JUL-92
>;
>;
>; Start of privileged task build at 10:30:53 on 12-JUL-92
>;
>;
>;      Note that the following tasks will be built for your system:
>;
>;       BOO    DMO     COT     FCPMDL  ICP     INI     INS     
>;       PMT    MCR     DCL     MOU     QMG     QMGCLI  QMGPRT  
>;       LPP    F11MSG  MTAACP  SAV     TKTN    UFD     LOA     
>;       UNL    PMD     RMD     SHF     ACNT    BYE     HEL     
>;       BRO    SHUTUP  ACS     ERRLOG  ELI     
>;
>;
>;
>;
>; It is assumed that [1,1]FCSRES.STB is an ANSLIB version of the FCS
>; resident library
>;
>;
>; Creating the task build .CMD and .ODL files in SY:[1,24]
>;
>TKL @SY:[1,24]BOOBLD.CMD
>TKL @SY:[1,24]DMOBLD.CMD
>TKL @SY:[1,24]COTRESBLD.CMD
>TKL @SY:[1,24]FCPMDLBLD.CMD
>TKL @SY:[1,24]ICPBLD.CMD
>TKL @SY:[1,24]INIBLD.CMD
>TKL @SY:[1,24]INSBLD.CMD
>TKL @SY:[1,24]PMTBLD.CMD
>TKL @SY:[1,24]MCMBLD.CMD
>TKL @SY:[1,24]DCLBLD.CMD
>TKL @SY:[1,24]MOUBLD.CMD
>TKL @SY:[1,24]QMGRESBLD.CMD
>TKL @SY:[1,24]QCLRESBLD.CMD
>TKL @SY:[1,24]QPRBLD.CMD
>TKL @SY:[1,24]LPPRESBLD.CMD
>TKL @SY:[1,24]F11MSGBLD.CMD
>TKL @SY:[1,24]MTABLD.CMD
>TKL @SY:[1,24]SAVBLD.CMD
>TKL @SY:[1,24]TKNBLD.CMD
>TKL @SY:[1,24]UFDBLD.CMD
>TKL @SY:[1,24]LOABLD.CMD
>TKL @SY:[1,24]UNLRESBLD.CMD
>TKL @SY:[1,24]PMDRESBLD.CMD
>TKL @SY:[1,24]RMDBLD.CMD
>TKL @SY:[1,24]SHFBLD.CMD
>TKL @SY:[1,24]ACNRESBLD.CMD
>TKL @SY:[1,24]BYEBLD.CMD
>TKL @SY:[1,24]HELRESBLD.CMD
>TKL @SY:[1,24]BROBLD.CMD
>TKL @SY:[1,24]SHUBLD.CMD
>TKL @SY:[1,24]ACSRESBLD.CMD
>TKL @SY:[1,24]ERLBLD.CMD
>TKL @SY:[1,24]ELIRESBLD.CMD
>;
>; End of privileged task build at 10:32:10 on 12-JUL-92
>;
>;
>; Start of system VMR at 10:32:10 on 12-JUL-92
>;
>SET /UIC=[1,54]
>;
>INS $BOO;-1
>INS $VMR;-1
>ASN SY:=LB:
>VMR @SYSVMR
VMR -- *DIAG*-Partition reduced to executive common size
INS EXCOM1
VMR -- *DIAG*-Partition reduced to executive common size
INS EXCOM2
VMR -- *DIAG*-Loadable driver larger than 4K
LOA TT:
VMR -- *DIAG*-Installed tasks may no longer fit in partition
SET /TOP=DRVPAR:-*
POOL=1200:10746.:10746.
EXCOM1 117734 120000 014700 MAIN COM
EXCOM2 117670 134700 010200 MAIN COM
LDRPAR 117624 145100 002600 MAIN TASK
TTPAR  117260 147700 040000 MAIN TASK
DRVPAR 116734 207700 013300 MAIN SYS 
       116670 207700 002100 SUB  DRIVER - DB:
       116570 212000 002100 SUB  DRIVER - DL:
       116470 214100 001100 SUB  DRIVER - LP:
       116370 215200 004500 SUB  DRIVER - MS:
       116270 221700 000500 SUB  DRIVER - PP:
       116170 222400 000300 SUB  DRIVER - PR:
       116070 222700 000300 SUB  DRIVER - CO:
SYSPAR 116024 223200 011700 MAIN TASK
FCSRES 115760 235100 040000 MAIN COM
FCPPAR 115714 275100 024200 MAIN SYS 
GEN    115650 321300 436500 MAIN SYS 
LDR... 13.02  117510 LDRPAR 248. 002600 LB0:-00104414 FIXED
TKTN   05.00  111164 SYSPAR 248. 011700 LB0:-00110230
...RMD 03.00  114510 GEN    225. 027200 LB0:-00112200
F11MSG 13.00  113600 GEN    200. 005700 LB0:-00110247
MTAACP 15.01  113464 GEN    200. 014700 LB0:-00111734
...DMO 04.00  114144 GEN    160. 014600 LB0:-00107317
MCR... 07.00  112440 SYSPAR 160. 011700 LB0:-00110133
...DCL 5.04   112324 GEN    160. 051500 LB0:-00110610
...MOU 27.01  111644 GEN    160. 037700 LB0:-00110465
...MCR 07.00  111300 GEN    160. 020000 LB0:-00110274
F11ACP 06.01  115534 FCPPAR 149. 024200 LB0:-00107413
ERRLOG 2.00   114030 GEN    148. 040000 LB0:-00112575
PMT... 2.00   113004 GEN    148. 006300 LB0:-00107573
COT... 2.0    115420 GEN    145. 013600 LB0:-00107336
PMD... 08.01  112670 GEN    140. 016200 LB0:-00111625
SHF... 6.00   111414 SYSPAR 105. 011700 LB0:-00111665
...INS 9.01   113120 GEN    100. 034600 LB0:-00110062
...SAV 05.00  111530 GEN    100. 033300 LB0:-00112116
...UFD 05.00  111050 GEN    100. 005700 LB0:-00110261
QMG... 03.04  115304 GEN     75. 031700 LB0:-00110543
PRT... 2.0    114740 GEN     70. 001100 LB0:-00110243
LP0    06.00  114624 GEN     70. 014500 LB0:-00111522
...ACS 3.00   114374 GEN     70. 005000 LB0:-00111722
...AT. 9.0    113234 GEN     64. 060000 LB0:-00107665
...QUE 05.01  115170 GEN     50. 020100 LB0:-00111327
...PRI 05.01  115054 GEN     50. 020100 LB0:-00111327
...BOO 06.02  114260 GEN     50. 022000 LB0:-00107251
...ELI 1.00   113714 GEN     50. 017300 LB0:-00112641
...MAG 03.00  113350 GEN     50. 031500 LB0:-00110162
...LOA 04.02  112554 GEN     50. 032600 LB0:-00111570
...HEL 04.00  112210 GEN     50. 024100 LB0:-00112451
...BYE 07.00  112074 GEN     50. 012700 LB0:-00111705
...BRO 07.00  111760 GEN     50. 030400 LB0:-00112516
...UNL 4.02   110734 GEN     50. 024500 LB0:-00111471
LP0:    Loaded
PP0:    Loaded
PR0:    Loaded
DB0:    Loaded
DB1:    Loaded
DL0:    Loaded
DL1:    Loaded
DL2:    Loaded
DL3:    Loaded
MS0:    Loaded
CO0:  TT0:
TT0:    Loaded
TT1:    Loaded
TT2:    Loaded
TT3:    Loaded
TT4:    Loaded
TT5:    Loaded
TT6:    Loaded
TT7:    Loaded
TT10:    Loaded
NL0:  
TI0:  
CL0:  TT0:
LB0:  DB0:
SY0:  DB0:
>;
>; End of system VMR at 10:32:12 on 12-JUL-92
>;
>;
>; An alternate version of SYSLIB.OLB, the system object library, was
>; created to provide support for ANSI magtape/FCS big-buffering (which
>; you selected in Phase I).  You may want to rebuild DMP, FLX, PIP, and 
>; VFY in Phase III to use ANSLIB.OLB.  Note, however, building tasks with
>; ANSLIB.OLB causes an increase in the size of tasks as compared to the
>; SYSLIB.OLB version of the tasks.
>;
>; A memory resident library of FCS routines (which you selected in Phase I)
>; was built to help reduce task memory requirements.  You may want to rebuild
>; tasks in Phase III to link to the FCS resident library.
>; 
>; When SYSGEN finishes, boot in your target system, and save the system with a
>; bootstrap.  For example:
>;
>;     >BOO [1,54]RSX11M
>;      RSX11M V4.6 BL56 
>;
>;
>;      >TIM 12:00 14-JUN-85
>;     >SAV /WB
>; 
>;      RSX11M V4.6 BL56        124.K   MAPPED
>;     >RED DB:=SY:
>;     >RED DB:=LB:
>;     >MOU DB:RSXM56
>;     >@DB:[1,2]STARTUP
>;     .
>;     .
>;     .
>;
>REM PIP
>REM EDI
>REM LBR
>REM TKL
>;
>; End of SYSGEN phase II at 10:32:12 on 12-JUL-92
>;
>SET /UIC=[200,200]
>@ <eof>
>boot [1,54]rsx11m
RSX11M V4.6 BL56  

>
  SAV /WB

  RSX-11M V4.6 BL56   124.K MAPPED

>RED DB:=SY:
>RED DB:=LB:
>MOU DB:RSXM56
>@DB:[1,2]STARTUP
>* PLEASE ENTER TIME AND DATE (HR:MN DD-MMM-YY) [S]: 10:35 12-JUL-92
>TIM 10:35 12-JUL-92
>* ENTER LINE WIDTH OF THIS TERMINAL [D D:132.]: 
>SET /BUF=TI:132.
>ACS SY:/BLKS=1024.
>;
>; This system startup command file (LB:[1,2]STARTUP.CMD) contains a
>; template of commands to initialize the queue print spooler and queue
>; LP0:, initialize the error logger, initialize the DCL CLI, and install
>; the RMS Library and Utilities.  As is these commands are commented out
>; and are not executed.  To include these commands as part of the
>; startup procedure, edit the file to remove the period and semi-colon
>; (.;) comment delimiter from the beginning of each line.  These
>; commands may be useful for initializing the various facilities for
>; your installation or else they may provide a model with which to
>; tailor initialization commands for your particular installation. 
>;
>@ <eof>

Note about VMR

As seen in the log, the SYSGEN procedure executes automatically VMR to generate the bootable system image. This automatic execution happens only when you are SYSGENing a baseline system. If you have to SYSGEN again a running, online system, SYSGEN does not execute VMR for you. This is an important difference between 11M and 11M+. In that case, you have to add some magic to get a correct VMR execution:

>SET /UIC=[1,54]
>ASN DB0:=LB:
>INS DB0:VMR
>VMR @SYSVMR.CMD

Then you can soft-boot the new system and save the image to disk:

>BOOT RSX11M
.
.
.
>SAV /WB

SYSGEN Phase 3

During phase 3 we can build/rebuild the system tasks, both privileged and non-privileged. This will allow us to patch or modify the tasks, or add tasks which are not built by default. You will probably want to build at least EDT (unless you like the default editor, EDI). In this example we will be building ALL the non-privileged tasks. If you are using real hardware you will not want to do this, since it will take a lot of time; using emulated hardware that is a non-issue, so I'll built all the stuff...

>SET /UIC=[200,200]
>@SYSGEN3
>INS $PIP
>INS $EDI
>INS SY:[1,54]TKB.TSK;1/TASK=...TKL
>;
>; RSX-11M V4.6 System Generation PHASE III -- Version 04.06
>;
>; 12-JUL-92 10:35:22
>;
>*  1. In what UIC is SGNPARM.CMD if not in [200,200] [S]: 
>;
>; Big disk distribution kit SYSGEN version 04.17 for RSX-11M BL56  
>;
>; Continuation from SYSGEN PHASE I done on 12-JUL-92 at 10:30:37
>;
>*  2. Are you building nonprivileged tasks? [Y/N]: Y
>*  4. Enter map device (ddu:) [D: NL:] [S]: 
>ASN SY:=LB:
>;
>;      For nonprivileged tasks:  * -- Prints the table of tasks
>;                                % -- Builds all tasks
>;                                . -- Terminates inquiry
>;
>;      Enter responses separated by commas.  All responses need
>;      not fit on one line.
>;
>; Example:  BAD,LBR,PIP,.
>;
>* 5. Enter task name(s) [S]: *
>;
>;      Nonprivileged tasks:
>;
>;              BAD     BRU     CDA     CFL     CMP
>;              CRF     DMP     DSC     EDI     EDT
>;              FLX     FMT     FTB     IOX     LBR
>;              MAC     PAT     PIP     RPT     SLP
>;              TKB     VFY     VMR     ZAP
>;
>* 5. Enter task name(s) [S]: %
>;
>; [1,1]FCSRES.STB can be used to build many tasks
>; so that those tasks link to the FCS resident library
>;
>*  6. Use [1,1]FCSRES.STB when building those tasks? [Y/N]: 
>;
>; LB:[1,1]ANSLIB.OLB can be used to build certain tasks
>; so that those tasks have ANSI/big-buffered support
>;
>*  7. Use LB:[1,1]ANSLIB.OLB when building those tasks? [Y/N]: 
>* 11. Pause to edit any task build .CMD or .ODL files? [Y/N]: 
>* 12. Delete task build .CMD and .ODL files after task building? [Y/N]: 
>SET /UIC=[1,24]
>;
>; Creating the task build .CMD and .ODL files in SY:[1,24]
>;
>TKL @SY:[1,24]BADBLD.CMD
>TKL @SY:[1,24]BRUBLD.CMD
>TKL @SY:[1,24]CDABLD.CMD
>TKL @SY:[1,24]CFLBLD.CMD
>TKL @SY:[1,24]CMPBLD.CMD
>TKL @SY:[1,24]CRFBLD.CMD
>TKL @SY:[1,24]DMPBLD.CMD
>TKL @SY:[1,24]DSCBLD.CMD
>TKL @SY:[1,24]EDIBLD.CMD
>TKL @SY:[1,24]EDTBLD.CMD
>TKL @SY:[1,24]FLXBLD.CMD
>TKL @SY:[1,24]FMTBLD.CMD
>TKL @SY:[1,24]FTBBLD.CMD
>TKL @SY:[1,24]IOXBLD.CMD
>TKL @SY:[1,24]LBRBLD.CMD
>TKL @SY:[1,24]MACBLD.CMD
>TKL @SY:[1,24]PATBLD.CMD
>TKL @SY:[1,24]PIPBLD.CMD
>TKL @SY:[1,24]RPTBLD.CMD
>TKL @SY:[1,24]SLPBLD.CMD
>TKL @SY:[1,24]TKBBLD.CMD
>TKL @SY:[1,24]VFYBLD.CMD
>TKL @SY:[1,24]VMRBLD.CMD
>TKL @SY:[1,24]ZAPBLD.CMD
>ASN =LB:
>REM PIP
>REM EDI
>REM TKL
>SET /UIC=[200,200]
>@ <eof>
>RUN $SHUTUP

RSX11M SHUT DOWN PROGRAM


Enter minutes to wait before shutdown: 0
OK to shutdown? [Y/N]: Y
 All further logins are disabled 
 12-JUL-92 10:37 System is now shutting down -- RSX11M

@LB:[1,2]SHUTUP


>
ACS DB0:/BLKS=0.
ACS -- Checkpoint file now inactive
>
DMO DB0:/DEV

DMO -- System disk being dismounted
DMO -- SYSTEM  dismounted from DB0:    *** Final dismount initiated ***
10:37:40  *** DB0: -- Dismount complete

>
SHUTUP operation complete

HALT instruction, PC: 124122 (CLRB @#177776)
sim> quit
Goodbye
And this is it! Now we have a bootable, complete RSX11M system. The only missing things are the HELP support, the configuration of the STARTUP.CMD procedure and the creation and management of the accounts file, which we will leave for the third and last post of the series. Meanwhile, I suggest to make another copy of the RP06.000 file so we can revert to a pristine system just in case we break it badly during our experimentation...

Credits

I've added a pair of improvements and corrected a quite big error as suggested by Oleg Safiullin. Thanks, Oleg for your help.

Installing RSX-11M 4.6 from scratch - Part 1: Creating the baseline system

A little bit of background

The first computer I had to work with was a VAX 8250  the company bought to replace a PDP-11/60 which was being used mainly to manage the catalog of a network of public libraries (at that time, it was the first mechanized catalog implemented in this country). The 11/60 ran a home-built catalog program, based on the library managing standards of the time, written in FORTRAN. Some terminal users did they data-entry work using VT52 screens, and once a month a batch process generated a tape which was used to generate microfiches which were distributed to the library network, so the whole catalog was accessible from every library. For the 70's - early 80's it was a huge improvement...

I was hired as part of the team which had to set up the new VAX, and with the goal to expand the computer usage to other parts of the "business". For that reason I never paid enough attention to the "old" PDP. I remember the guy who managed it typing in a printing terminal and talking about SYSGEN-ing the system, going around replacing RP06 disk packs and doing all kinds of weird things.

Of course now I regret the fact I mostly ignored that nice machine. Fortunately, with the advent of that awesome piece of software called simh, and with the growing pile of documentation and software available on the internet, I can partially repair that mistake. Of course I'll never be a "PDP pro", but I least I want to know how does it feel to operate one of those wonderful machines. 

Now, enough of rusting memories. My goal is now to set up a functioning RSX11M system under simh, and doing it from scratch. It's relatively easy to find pre-built systems images in the net, but this time I want to do it from scratch, using a tape distribution, and over a "virgin" machine...

Bill of materials

To setup our new system we need:
When you unzip the rsx11m46.zip file you'll get the tape image in TPC format; just remember to tell SIMH you are using that format instead of the native SIMH format or it won't work.

We'll need also a good PDP11 configuration for simh. My configuration tries to ressemble the one of the PDP11/60 I mentioned before:

  • 128 KWords of memory.
  • Two RP06 disks.
  • Two RL02 removable disks.
  • Line printer.
  • DZ11 terminal multiplexer with 8 lines.
  • TSxx tape drive.
It's convenient to use a INI file to set up simh. This is the one I'm using:

;---------------------------------------------------------------
; Disable devices, we'll enable what we need later 
;---------------------------------------------------------------
set CR disable
set DZ disable
set HK disable
set RK disable
set RL disable
set RP disable
set RQ disable
set RQB disable
set RQC disable
set RQD disable
set RX disable
set RY disable
;set TA disable
set TC disable
set TM disable
set TS disable
set TQ disable
set TU disable
set VH disable
set XQ disable
set XQB disable
set XU disable
set XUB disable

echo PDP-11/45 with 128 kwords of memory
echo 
set cpu 11/45
set cpu 256k
set cpu idle

SET RL enable
set RL0 RL02
set RL1 RL02

SET RP ENABLE
SET RP0 RP06
ATTACH RP0 RP06.000
SET RP1 RP06
;ATTACH RP1 RP06.001

SET TS ENABLE
SET TS0	FORMAT=TPC
SET TS0 LOCKED

SET DZ ENABLE
SET DZ LINES=8
ATTACH -am DZ 11023

SET LPT ENABLE
ATTACH LPT PRINTER.TXT

The install procedure

The task of setting up a new RSX11M system has three basic steps:
  1. Create the baseline bootable disk from the distribution tape.
  2. Running SYSGEN to generate an executive tailored to your machine configuration, as well as the necessary privileged and unprivileged tasks.
  3. Tailoring the system to your needs or tastes.
This first post covers just the first of these three steps. What follows is a slightly edited console log. I've tried to make it a little bit more readable and I have highlighted the typed commands and responses in bold. The configuration file, pdp11.ini, is the one listed above. Please tell me if you find any mistake in the log so I can correct it...

Macjordi:rsx11m46 jguillaumes$ pdp11 pdp11.ini

PDP-11 simulator V3.8-1
sim> do pdp11.ini
PDP-11/45 with 128 kwords of memory

RP: creating new file
Overwrite last track? [N] y
Listening on port 11023 (socket 5)
Modem control activated
Auto disconnect activated
LPT: creating new file
sim> 
sim> attach rsx11m46.tpc
sim> boot ts0


RSX-11M/RSX-11M-PLUS Standalone Copy System V04


RSX-11M/RSX-11M-PLUS Standalone Configuration and Disk Sizing Program

Valid switches are:
        /CSR=nnnnnn to change the default device CSR
        /VEC=nnn to change the default device vector
        /FOR=n to change the default magtape formatter number
        /DEV to list all default device CSR and vectors


Enter first device: MS0:
Enter second device: DB0:
Hit RETURN and enter date and time as 'TIM HH:MM MM/DD/YY'


>TIM 10:24 07/12/92
>TIM
10:24:01 12-JUL-92
>RUN BAD
BAD>DB0:
BAD -- DB0: Total bad blocks= 0.
BAD>^Z
>RUN BRU
BRU>/REW/INIT/BAC:DBSYS MS0: DB0:

BRU - Starting Tape 1 on MS0:
BRU - End of Tape 1 on MS0:
BRU - Completed


BRU>

<ctrl-e>
Simulation stopped, PC: 001344 (CLRB (R1)+)
sim> boot rp


  RSX-11M V4.6 BL56   124.K MAPPED (BASELINE)

>RED DB:=SY:
>RED DB:=LB:
>MOU DB:RSXM56
>@DB:[1,2]STARTUP

>* PLEASE ENTER TIME AND DATE (HR:MN DD-MMM-YY) [S]: 10:26 12-JUL-92

>TIM 10:26 12-JUL-92

>* ENTER LINE WIDTH OF THIS TERMINAL [D D:132.]: 
>SET /BUF=TI:132.
>ACS SY:/BLKS=1024.
>@ 


>@TAPEKIT

>;
>; RSX-11M V4.6 BL56 tape distribution kit extraction procedure.
>;      Started on 12-JUL-92 at 10:26:12
>;

>INS LB:$BRU

>;
>* Enter drive and unit with tape distribution kit [ddn:] [S]: MS0:
>LOA MS:/PAR=GEN
>;
>; Copying rest of RSXM56 to DB0: ...
>;
>BRU/DENS:1600/NOINI/SUP/UFD/BAC:RSXBAS MS0: DB0:
BRU - Starting Tape 1 on MS0:
BRU - End of Tape 1 on MS0:
BRU - Completed
>BRU/DENS:1600/NOINI/SUP/UFD/BAC:EXCPRV MS0: DB0:
BRU - Starting Tape 1
BRU - End of Tape 1
BRU - Completed
>BRU/DENS:1600/NOINI/SUP/UFD/BAC:PRVBLD MS0: DB0:
BRU - Starting Tape 1
BRU - End of Tape 1
BRU - Completed
>BRU/DENS:1600/NOINI/SUP/UFD/BAC:RLUTIL MS0: DB0:
BRU - Starting Tape 1
BRU - End of Tape 1
BRU - Completed
>BRU/DENS:1600/NOINI/SUP/UFD/BAC:MCRSRC MS0: DB0:
BRU - Starting Tape 1
BRU - End of Tape 1
BRU - Completed
>BRU/DENS:1600/NOINI/SUP/UFD/BAC:HLPDCL MS0: DB0:
BRU - Starting Tape 1
BRU - End of Tape 1
BRU - Completed
>BRU/DENS:1600/NOINI/SUP/UFD/BAC:RMSV20 MS0: DB0:
BRU - Starting Tape 1
BRU - End of Tape 1
BRU - Completed
>;
>;      Completed on 12-JUL-92 at 10:26:32
>;
>@ <eof>
>

<ctrl-e>
Simulation stopped, PC: 002770 (CLRB (R1)+)
sim> 

At this point we have a disk image, RP06.000, which contains the baseline system. This is a good moment to make a copy of that image file (probably in compressed format) so we can't go back to this point in case we make any mistake during the next steps of the install. It's nice to have this baseline to make clones and generate other configurations if we want to experiment.

If you take a look at the BRU command line, it references a BackupSet named DBSYS. That is the backupset to use to generate an RP06 based baseline system. If you are going to use different disks the backupset name can be different. The names are listed in the referenced manual, but I'm copying the list here for your convenience:

Disk TypeName
RP04/05/06DBSYS
RL01/02DLSYS
RK06/07DMSYS
RM02/03/05/80DRSYS
RA60/80/81DUSYS
RC25/RD52/53DUSYS

On the next post we'll proceed to do the first SYSGEN of our system, and we will end with a fully usable, but untailored RSX11M 4.6 operating system.