NAME

intro ­ Introduction to Section 2: System Services

DESCRIPTION

This section describes the following pSOSystem system services:

NAME

bootpd - BOOTP daemon

DESCRIPTION

The bootpd server in pSOSystem networking utilities is an implementation of the BOOTSTRAP protocol server and is based on RFC 951 and RFC 1395. It provides additional features by implementing: (a) a tag field (ps) in the bootpd configuration database, which identifies the forwarding server to which bootp requests from a specific hardware device can be forwarded; (b) an optional default parent bootpd server address (parentIP) in the bootpd configuration table to which unresolved BOOTP requests can be forwarded.

bootpd creates a daemon task, BTPD, to handle BOOTP requests from clients. When BTPD starts, it reads configuration information from a user-supplied string, which it stores in its hash tables. When a BOOTP request comes in, if there is a match in the BTPD configuration database, BTPD first verifies whether the forwarding server field (ps) is set for the matching address. If it is set, the request is forwarded to the specified server regardless of other fields. Otherwise, BTPD processes the request and may send back a reply packet, if appropriate. If no match is found in BTPD's configuration database and a parent bootpd server is supplied when BTPD starts, BTPD forwards requests to its parent server.

The bootpd server in the pSOSystem operating systemalways ignores the server name field in BOOTP requests.

System/Resource Requirements

To use the bootpd server, you must have the following components installed:

In addition, bootpd requires the following system resources:

Starting the Routing Daemons

In order to use bootpd in an application, you need to link the pSOSystem network utilities library. bootpd is started with bootpd_start(bootpdcfg_t *). The following code fragment gives an example of a database string and shows how to start bootpd:

#include <netutils.h> 

char *bootp_table = 
"scg.dummy:\ 
           sm=255.255.255.0:\
           td=3.0:\
           hd=/tftpboot:\
           bf=null:\
           dn=isi.com:\
           hn:\n\
subnetscg.dummy:\
           tc=scg.dummy:\
           gw=192.103.54.14:\
           ps=1.2.3.4:\n\
board1:\
           tc=subnetscg.dummy:\
           ht=ethernet:\
           ha=08003E20F810:\
           ip=192.103.54.229:\
           bf=ram.hex:\
           bs=123:\
           ps@:\
";

void start_bootpd_server()
{
static bootpdcfg_t bootpd_cfg;

     bootpd.priority = 200;
     bootpd_cfg.flags = BOOTPD_SYSLOG;
     bootpd_cfg.bootptab = bootp_table;
     bootpd_cfg.parentIP.s_addr = htonl(0xC0D8E61D);

     if (bootpd_start(&bootpd_cfg))
         printf("bootpd_start: failed to start\n");
} 

The BOOTP Daemon Configuration Table and Database String

The bootpd server requires a user-supplied configuration table, defined as follows:

struct {
   unsigned long priority;       /* priority of BTPD task */
   unsigned long flags;          /* optional flags */
   char *bootptab;               /* bootpd database string */
   struct in_addr parentIP;      /* parent BOOTP server IP address */
   unsigned long reserved[2];    /* reserved for future */
}  bootpdcfg_t;
typedef struct bootpdcfg_t bootpdcfg_t;

priority
This defines the priority at which the BTPD daemon task starts executing.

flags
This specifies the following bootpd server options:

BOOTPD_SYSLOG This displays logging information on the pREPC+ standard error channel.

bootptab
This is a pointer to a string that contains the bootpd configuration database. The string is defined as follows:
        "hostname:\
     tg=value:\
      ...\
    tg=value:\n\
    hostname:\
      tg=value:\
      ...\
    tg=value:"

where hostname is the actual name of a BOOTP client and tg is a two-character tag symbol. Most tags must be followed by an equals sign and a value, as above. Some may also appear in a boolean form with no value (i.e. tg:). For a list of currently recognized tags, see Section on page -6.

parentIP
This is the IP address in network byte order of this server's parent server, to whom this server can forward BOOTP requests.

Two-Character Tag Symbols

The following tags are currently recognized by the bootpd server:

bf Bootfile
bs Bootfile size in 512-octet blocks
cs Cookie server address list
dn Domain name
ds Domain name server address list
gw Gateway address list
ha Host hardware address
hd Bootfile home directory
hn Send client's hostname to client
ht Host hardware type (see Assigned Numbers RFC)
im Impress server address list
ip Host IP address
lg Log server address list
lp LPR server address list
ns IEN-116 name server address list
rl Resource location protocol server address list
rp Root path to mount as root
sa TFTP server address client should use
ps BOOTP server address forwarding server should use
sm Host subnet mask
sw Swap server address
tc Table continuation (points to similar "template" host entry)
td TFTP root directory used by TFTP servers
to Time offset in seconds from UTC (Universal Time Coordinate)
ts Time server address list
vm Vendor magic cookie selector

There is also a generic tag, T n, where n is an RFC1084 vendor field tag number. Thus, it is possible to immediately take advantage of future extensions to RFC1084 without being forced to modify bootpd first. Generic data may be represented as either a stream of hexadecimal numbers or as a quoted string of ASCII characters. The length of the generic data is automatically determined and inserted into the proper field(s) of the RFC1084-style BOOTP reply.

The following tags take a white space-separated list of IP addresses: cs, ds, gw, im, lg, lp, ns, rl, and ts. The ip, sa, ps, sw, and sm tags each take a single IP address. All IP addresses are specified in standard Internet ``dot'' notation and may use decimal, octal, or hexadecimal numbers (octal numbers begin with 0, hexadecimal numbers begin with '0x' or '0X').

The ht tag specifies the hardware type code as either an unsigned decimal, octal, or hexadecimal integer, or as one of the following symbolic names: ethernet or ether for 10Mb Ethernet, ethernet3 or ether3 for 3Mb experimental Ethernet, ieee802, tr, or token-ring for IEEE 802 networks, pronet for Proteon ProNET Token Ring, or chaos, arcnet, or ax.25 for Chaos, ARCNET, and AX.25 Amateur Radio networks, respectively. The ha tag takes a hardware address, which must be specified in hexadecimal; optional periods and/or a leading '0x' may be included for readability. The ha tag must be preceded by the ht tag (either explicitly or implicitly; see tc below).

The td tag is used to inform bootpd of the root directory used by tftpd. The hd tag is actually relative to the root directory specified by the td tag. For pHILE+ files, the td tag should always be there to include the volume name. For Sun files, the td tag is optional. For example, if your BOOTP client bootfile is /tftpboot/bootimage on volume 3 in your system, then specify the following in the bootptab string:

:td=3.0:hd=/tftpboot:bf=bootimage:

The hostname, home directory, and bootfile are ASCII strings that may be optionally surrounded by double quotes ("). The client's request and the values of the hd and bf symbols determine how the server fills in the bootfile field of the BOOTP reply packet.

If the client specifies an absolute pathname (an absolute pathname in the pHILE+ file system manager begins with a volume name followed by a complete path) and that file exists on the server machine, that pathname is returned in the reply packet. If the file cannot be found, the request is discarded; no reply is sent. If the client specifies a relative pathname, a full pathname is formed by prepending the value of the hd tag and testing for existence of the file. If the hd tag is not supplied in the configuration file or if the resulting boot file cannot be found, then the request is discarded.

Clients that specify null boot files always elicit a reply from the server. The exact reply depends again upon the hd and bf tags. If the bf tag gives an absolute pathname and the file exists, that pathname is returned in the reply packet. Otherwise, if the hd and bf tags together specify an accessible file, that filename is returned in the reply. If a complete filename cannot be determined or the file does not exist, the reply will contain a zeroed-out bootfile field.

In all these cases, existence of the file means that, in addition to actually being present, the file must have read access to public, since this is required by tftpd to permit the file transfer. Also, all filenames are first tried as filename.hostname and them simply as filename, thus providing for individual per-host bootfiles.

The sa tag may be used to specify the IP address of the particular TFTP server you wish the client to use. In the absence of this tag, bootpd tells the client to perform TFTP to the same machine bootpd is running on.

The ps tag may be used to specify the IP address of a peer BOOTP server address to which the BOOTP request will forward.

The time offset to may be either a signed decimal integer specifying the client's time zone offset in seconds from UTC, or the keyword auto, which sets the time zone offset to 0. Specifying the to symbol as a boolean has the same effect as specifying auto as its value.

The bootfile size bs may be either a decimal, octal, or hexadecimal integer specifying the size of the bootfile in 512-octet blocks, or the keyword auto, which causes the server to automatically calculate the bootfile size at each request. As with the time offset, specifying the bs symbol as a boolean has the same effect as specifying auto as its value.

The vendor magic cookie selector (the vm tag) may take one of the following keywords: auto (indicating that vendor information is determined by the client's request), rfc1048 or rfc1084 (which always forces an RFC1084-style reply).

The hn tag is strictly a boolean tag; it does not take the usual equals-sign and value. It's presence indicates that the hostname should be sent to RFC1084 clients. bootpd attempts to send the entire hostname as it is specified in the configuration file; if this will not fit into the reply packet, the name is shortened to just the host field (up to the first period, if present) and then tried. In no case is an arbitrarily-truncated hostname sent (if nothing reasonable will fit, nothing is sent).

Often, many host entries share common values for certain tags (such as name servers, etc.). Rather than repeatedly specifying these tags, a full specification can be listed for one host entry and shared by others via the tc (table continuation) mechanism. Often, the template entry is a dummy host that does not actually exist and never sends BOOTP requests. Note that bootpd allows the tc tag symbol to appear anywhere in the host entry. Information explicitly specified for a host always overrides information implied by a tc tag symbol, regardless of its location within the entry. The value of the tc tag may be the hostname or IP address of any host entry previously listed in the configuration file.

Sometimes it is necessary to delete a specific tag after it has been inferred via tc. This can be done using the construction tag @ which removes the effect of tag. For example, to completely undo an IEN-116 name server specification, use ":ns@:" at an appropriate place in the configuration entry. After removal with @, a tag is eligible to be set again through the tc mechanism.

Host entries are separated from one another by new lines in the configuration string; a single host entry may be extended over multiple lines if the lines end with a backslash (\). It is also acceptable for lines to be longer than 80 characters. Tags may appear in any order, with the following exceptions: the hostname must be the very first field in an entry, and the hardware type must precede the hardware address.

NAME

Boot ROMs - Applications for downloading executable images from the host to the target

DESCRIPTION

The pSOSystem Boot ROMs from Integrated Systems support a number of commercial computer boards. Boot ROMs are used for downloading executable images from the host machine to the target system, starting the images, and debugging the downloaded code.

The Boot ROMs are a pSOSystem application that contains the pSOS+ kernel, the pROBE+ debugger, the pNA+ network manager, drivers, and initialization code. The ROMs support serial and Ethernet host-target connections, and they can operate in single and multiprocessor configurations. ISI recommends that first-time users start with the Boot ROMs in a single-processor system, even if the intended configuration is multiprocessor. The source code is supplied as part of the pSOSystem operating system and can be customized for a particular target configuration. For instructions on how to install ROMs on a particular target, see Appendix B of pSOSystem Getting Started. "Board-Specific Information".

Single-Processor Configuration

Upon first-time powerup, the ROMs must connect to a terminal through an RS-232 connection to allow you to configure setup code for the target. (If the configuration information is stored in non-volatile RAM, reconfiguring is unnecessary upon subsequent power-ups.) If the target has more than one RS-232 port, you can determine the most appropriate port by referring to Appendix B in pSOSystem Getting Started. The characteristics of the terminal (or host machine terminal emulation program) should be: 9600 baud, 8-bit data, 1 stop bit, and no parity. A startup message similar to the following appears on the terminal:

pSOSystem V2.1.3
Copyright (c) 1992 - 1996, Integrated Systems, Inc.
---------------------------------------------------------------
STARTUP MODE:
  Boot into pROBE+ standalone mode
NETWORK INTERFACE PARAMETERS:
  IP Address on LAN is 999.999.99.999
  Shared memory interface is disabled
HARDWARE PARAMETERS:
  Serial channels will use a baud rate of 9600
  This board's memory will reside at 0x1000000 on the VME bus
  After board is reset, startup code will wait 60 seconds
----------------------------------------------------------------------
To change any of this, press any key within 60 seconds

If such a message fails to appear, check the following items:

The startup message shows the current ROM configuration parameters while the ROMs wait 60 seconds for input. If no key is pressed within this time, the ROMs proceed to operate according to the parameters in the startup message. If a key is pressed, the following message appears:

(M)odify any of this or (C)ontinue? [M]

Entering the default M starts configuration mode. In configuration mode, the ROMs display a series of prompts for the current configuration settings. The user can accept the system-displayed value at each prompt by pressing [Enter] (or [Return]) or enter a new value at a particular prompt. After the final entry, the ROMs print an updated summary of the configuration and again prompt for an m or a c. Entering a c causes an exit from configuration mode. Configuration mode begins with the following display:

For each of the following questions, you can press <Return> to select the value shown in braces, or you can enter a new value.
How should the board boot?
  1. pROBE+ standalone mode
  2. pROBE+ waiting for host debugger via a serial connection
  3. pROBE+ waiting for host debugger via a network connection
  4. Run the TFTP Bootloader
which one do you want? [1]

pROBE+ Standalone

Entering a 1 at the configuration mode prompt enables you to use a ROM-resident, standalone pROBE+ debugger to download a pSOSystem executable image and start that image. The pROBE+ debugger downloads the image by executing the DL command and starts the image by executing the GO command. (The pROBE+ User's Manual contains a complete description of the pROBE+ debugger.) Upon exit from configuration mode, the following pROBE+ sign-on banner similar to the one below appears:

pROBE+ V3.0.5 
COPYRIGHT 1990 - 1996, INTEGRATED SYSTEMS, INC.
ALL RIGHTS RESERVED

pROBE+>

SpOTLIGHT - Serial Connection

Entering a 2 at the configuration mode prompt causes the pROBE+ debugger to exit configuration mode, enter remote debug mode, and wait for a connection request from the SpOTLIGHT debugger over the serial channel. The serial connection you are using for communication to the pROBE+ debugger now needs to be used by the pROBE+ debugger to communicate with the SpOTLIGHT debugger, so if you are using a terminal emulator, such as the UNIX tip utility, exit the emulator at this time so that the SpOTLIGHT debugger can use the connection.

If you have a terminal connected to the target's console port, then this connection must be moved from the terminal to a port that the SpOTLIGHT debugger can connect to on the host system. (Remember to set up the host's port the same way as the terminal was set; that is, baud rate and stop bits).

The SpOTLIGHT User's Guide contains instructions for invoking the SpOTLIGHT debugger on the host system. The pSOSystem Getting Started manual contains a SpOTLIGHT tutorial.

SpOTLIGHT - Ethernet Connection

Entering a 3 at the configuration mode prompt puts the pROBE+ debugger in remote debug mode, after which the pROBE+ debugger waits for a connection request from the SpOTLIGHT debugger over the network. Because this mode requires a network interface, the program prompts for additional information about network interfaces, as follows:

Do you want an Ethernet interface? [N]

Enter a y. The pROBE+ debugger responds as follows:

What is this board's IP address on the Ethernet(0.0.0.0 = RARP)? [999.9.999.99]

In most cases, when the target CPU is connected to a host system by Ethernet, the target CPU is added to an existing network. As such, the target CPU must have an IP address that is compatible with that network. Consult your system administrator to obtain a usable IP address. The system administrator may need to modify one or more host system files to make the new IP address known to the host. When an Ethernet IP address becomes available, make it known to the ROMs by entering it at this point. IP addresses are entered as a sequence of four decimal numbers separated by periods, for example: 192.0.10.3

The BOOT ROMs can also obtain their IP address for Ethernet by RARP (Reverse Address Resolution Protocol), in which case a RARP server on the Ethernet assigns the IP address to the ROMs when they initialize. To force the ROMs to use RARP to get their IP address, enter 0.0.0.0 for the IP address.

After an IP address is entered, the following prompt appears:

Do you want to use a subnet mask for the Ethernet interface? [N]

In most cases the answer to this question is no. A y entry causes the ROMs to prompt for a subnet mask to use with the interface. Subnet masks are explained in the pSOSystem System Concepts manual.

The next prompt is

Is there a gateway node on the Ethernet to other networks? [N]

Usually, the host and target systems reside on the same network, in which case the answer to this question is no. In larger installations, however, the host and target systems may exist on two different networks. In such cases, the ROMs must have the IP address of a gateway on their network (to which they direct packets ultimately bound for the host system). A gateway node has access to two or more networks, and can thus transfer packets between them. A y entry in response to the preceding question causes the program to prompt for the IP address of this gateway node.

The next two questions are

Is this CPU the gateway between Ethernet and shared memory? [N]
Do you want a shared memory interface [N]

For a single-CPU system, the answer to both these questions should be no, so press [Return] twice.

Next, the ROMs step through the Hardware Configuration parameters, which probably won't need to change. Upon exit from Configuration Mode, no further console output appears because the target CPU is waiting for a connection from the SpOTLIGHT debugger.

Invoke the SpOTLIGHT debugger on the host system by following the instructions given in the SpOTLIGHT User's Guide. Be sure to specify use of Ethernet and designate the target CPU's IP address. the SpOTLIGHT debugger is now ready for use. The SpOTLIGHT User's Guide contains a brief introduction to the SpOTLIGHT debugger, and the pSOSystem Getting Started manual contains a short tutorial demonstrating its use.

EXAMPLE

The following is an example of a complete startup sequence:

pSOSystem V2.1.3
Copyright (c) 1992 - 1996, Integrated Systems, Inc.
----------------------------------------------------------------------
STARTUP MODE:
  Boot into pROBE+ standalone mode
NETWORK INTERFACE PARAMETERS:
  IP Address on LAN is 999.999.99.999
  Shared memory interface is disabled
HARDWARE PARAMETERS:
  Serial channels will use a baud rate of 9600
  This board's memory will reside at 0x1000000 on the VME bus
  After board is reset, startup code will wait 60 seconds
----------------------------------------------------------------------
To change any of this, press any key within 60 seconds

(M)odify any of this or (C)ontinue? [M] m
For each of the following questions, you can press <Return> to select the
value shown in braces, or you can enter a new value.

How should the board boot?
  1. pROBE+ standalone mode
  2. pROBE+ waiting for host debugger via a serial connection
  3. pROBE+ waiting for host debugger via a network connection
  4. Run the TFTP Bootloader

which one do you want? [1] 3

NETWORK INTERFACE PARAMETERS:
Do you want a LAN interface? [N]  y
This board's LAN IP address(0.0.0.0 = RARP)? [000.000.00.000]
000.000.00.000
Use a subnet mask for the LAN interface? [N] 
Do you want a shared memory network interface? [N] 
Should there be a default gateway for packet routing? [N]
HARDWARE PARAMETERS:
Baud rate for serial channels [9600] 
Bus address of this board's dual-ported memory [1000000] 
How long (in seconds) should CPU delay before starting up? [60] 5

----------------------------------------------------------------------
STARTUP MODE:
  Boot into pROBE+ and wait for host debugger via a network connection
NETWORK INTERFACE PARAMETERS:
  IP address on LAN is 000.000.00.000
  Shared memory interface is disabled
HARDWARE PARAMETERS:
  Serial channel will use a baud rate of 9600
  This board's memory will reside at 0x1000000 on the VME bus
  After board is reset, startup code will wait 5 seconds
 ---------------------------------------------------------------------

(M)odify any of this or (C)ontinue? [M]  c

TFTP Boot Loader

Entering a 4 at the configuration mode prompt selects the TFTP bootloader. It provides a mechanism whereby the BOOT ROMs, following a power-on/reset, can automatically download and initiate execution of a pSOSystem executable image without user intervention. The bootloader uses the TFTP protocols and can be used with any host system that supports TFTP. The SpOTLIGHT debugger is not required.

The TFTP bootloader in the ROMs has been designed for ease of use. In configuration mode, the user specifies the name of the S-record file that contains the executable image and the IP address of the host system on which it resides. When the ROMs exit configuration mode, the bootloader begins operating and loads the image into memory. When the image has been loaded, the bootloader transfers control to the entry point of the newly-loaded code.

When the TFTP bootloader has been selected as the operating mode, the ROMs prompt for additional information after the Network Interface Parameters questions. (Refer to ``SpOTLIGHT - Ethernet Connection,'' on page 2-12 for a discussion of these.) First, a prompt for the IP address of the host system appears:

IP address of the TFTP Boot server to boot from? [000.000.00.000]

Enter the IP address of the host system. The next question prompts for the name (possibly including a pathname) of the file to be loaded and started:

What is the name of the file to be loaded and started? [ram.hex] 

This should be the name of the S-record file (not the IEEE or a.out file) that contains the pSOSystem executable image intended for the current board. Rules that govern pathnames can vary between TFTP server implementations, but usually relative pathnames (no leading /) are interpreted relative to the /tftpboot directory. In this case, the default answer ram.hex would cause file /tftpboot/ram.hex to be loaded and started.

Multiprocessor Configurations

The ROMs contain a shared memory network interface, which allows target CPU's that share common memory to communicate with each other by packets that are passed in memory. The shared memory subsystem constitutes an IP network. The system board that serves as the gateway has access to both the shared memory and Ethernet networks. The board is a gateway because it routes packets between the two networks.

If the ROMs are intended to run on multiple target boards in this configuration, first set up and test the CPU that has the Ethernet connection (the gateway), as explained in the previous subsections. Then start the other CPUs as explained in the following subsections.

Initial Planning

Select one of the CPU's to be the gateway. The gateway has access to both the Ethernet and the shared memory, and thus needs two different IP addresses (one on each network). The IP address for the Ethernet can be the same address used for setup of the single-processor system.

The shared memory system is a separate network and must have its own network address. Consult with the system administrator when selecting a network address for the shared memory network, since it must be compatible with the rest of the system. When a network address for the shared memory system becomes available, assign host ID 1 to the gateway. For example, if the shared memory network address is 000.0.000, use 000.0.000.0 for the gateway.

For the remaining nodes in the system, assign IP addresses from the range 2 through 8 for each non-gateway CPU. In a 3-CPU system, for example, assign IP addresses 000.0.000.0 and 000.0.000.0 for the non-gateway CPU's.

Configuring the Gateway

To configure the gateway CPU in a multiprocessor system, select 3 or 4 from the menu, depending whether you want to use the SpOTLIGHT debugger or TFTP over the network. The following prompt appears:

NETWORK INTERFACE PARAMETERS:
Do you want a LAN interface?  [N] y

Respond with a y to this question, because this system will have a connection to the physical network to which the boot server is connected.

As in the case of a single processor system, next you must enter the IP address of this target:

This board's LAN IP address(0.0.0.0 = RARP)? [000.000.00.000]
Use a subnet mask for the LAN interface?  [N]

In this example, it is also assumed that there is no subnet mask. The next prompt asks for the IP address for a shared memory network:

IP address for shared memory? [000.00.000.0] 000.000.0.0

Enter the address of the network as discussed under ``Initial Planning.'' You may also have a subnet mask for the shared memory interface. In this example, it is assumed that there is no subnet mask:

Use a subnet mask for the shared memory interface?  [N]

The next question asks what node number this system will have in the multiprocessor system. Respond with the node number you are assigning to this target. Node number 1 is used in this example.

Which node number in the shared memory system is this?  [1] 

The shared memory system needs an area of memory to store a directory that all nodes can access. If you use the same memory map as the pSOSystem operating system, then that area is the reserved area at the base address plus 700. In this example 40000700 is used, which is the address of this board's dual-ported memory (its base address in the shared memory system) plus 700.

Bus address of the SMNI directory?  [1000600] 40000700

Note that this is the same address for all non-gateway targets in the system.

The following question depends on whether your SpOTLIGHT host or TFTP is on different network than this target system:

Should there be a default gateway for packet routing?  [N] 

In this example the host is on the same network, so the answer is no

The remaining questions are answered in the same way you would as with a single processor system, with the exception of the following question:

How many nodes will be using this as a gateway for bootloads? [1] 

You need to tell the gateway node how many other nodes will be using it to boot through, so that it can synchronize the multi-CPU boot.

The printout of the configuration should look something like this:

-----------------------------------------------------------------
STARTUP MODE:
   Run the TFTP Bootloader
NETWORK INTERFACE PARAMETERS:
   IP address on LAN is 000.000.00.000
   IP address on shared memory is 000.000.1.0
   Bus address of SMNI directory is 0x40000700
   This is node number 1 in the shared memory system
HARDWARE PARAMETERS:
   Serial channels will use a baud rate of 9600
   This board's memory will reside at 0x40000000 on the VME bus
TFTP BOOTLOADER PARAMETERS:
   IP address of the TFTP host is 000.000.00.000
   The file to download and start is ram.hex
   There will be 1 other nodes booting through this gateway
   After board is reset, startup code will wait 5 seconds
----------------------------------------------------------------
(M)odify any of this or (C)ontinue? [M] 

Configuring Non-Gateway Nodes

The other CPUs that will use the shared memory network are non-gateway nodes; these need to be configured as follows:

Do you want a LAN interface?  [Y] n
Do you want a shared memory network interface?  [Y] 

You can have a LAN interface and a shared memory network interface, but to make this example simpler, a LAN interface is assumed not to exist. You do need to answer yes to the shared memory network interface question.

As in the case of the gateway node, you need to supply an IP address. This address must consist of the same shared memory network address, plus a unique number from 1 to 8 for this target's node. For example:

IP address for shared memory? [000.000.0.0] 000.000.0.0

Next, answer no to the question on the subnet mask for the shared memory interface:

Use a subnet mask for the shared memory interface?  [N] 

Now you need to give the node number that you have assigned to this target:

Which node number in the shared memory system is this?  [1] 2

The next question on the SMNI directory must be answered the same as for the gateway node:

Bus address of the SMNI directory?  [40000700]

Next, give the IP address of the Gateway Node:

What is its IP address? [0.0.0.0] 000.000.0.0

The remaining questions are the same as for a single processor. The printout of the configuration should look something like this:

-----------------------------------------------------------------
STARTUP MODE:
   Run the TFTP Bootloader
NETWORK INTERFACE PARAMETERS:
   LAN interface is disabled
   IP address on shared memory is 000.000.0.0
   Bus address of SMNI directory is 0x40000700
   This is node number 2 in the shared memory system
   IP address of default gateway to other networks is 199.109.1.1
HARDWARE PARAMETERS:
   Serial channels will use a baud rate of 9600
   This board's memory will reside at 0x50000000 on the VME bus
TFTP BOOTLOADER PARAMETERS:
   IP address of the TFTP host is 000.000.00.000
   The file to download and start is ram.hex
   After board is reset, startup code will wait 5 seconds
----------------------------------------------------------------
(M)odify any of this or (C)ontinue? [M] 

Configuring the Host System

When interacting with the non-gateway nodes on the host system, the SpOTLIGHT debugger and/or the TFTP server daemon call the host system OS to send packets to IP addresses on the shared memory network. However, this network is unknown to the host system OS. Therefore, before attempting to communicate, the host OS must be able to detect the existence of the network and where to send the packets whose ultimate destination is on the network. On many UNIX systems (Sun, HP, and so on), the route command is used to give this information to the OS:

        route -n add 000.0.000.0 000.0.000.000 0

This informs the OS that network 000.0.000 (the shared memory network) can be accessed by directing packets to IP address 000.0.000.000 (the Ethernet IP address of the gateway CPU). The final parameter indicates the number of hops, in this case, 1. Use of the route command requires super user privileges.

NAME

FTP Client - Transfer files to and from a remote system

DESCRIPTION

The FTP (File Transfer Protocol) Client transfers files to and from a remote system. The remote system must run an FTP server program that conforms to the ARPANET File Transfer Protocol. The FTP Client runs as an application under pSH and is invoked with the following command:

        pSH> ftp [ remote_system ]

where remote_system is a remote system IP address.

If no arguments are given, FTP Client enters command mode (indicated by the ftp> prompt). In command mode, FTP accepts and executes commands described under "FTP Commands" on page -21.

If the command contains arguments, FTP executes an open command with those arguments. See ``FTP Commands'' for a description of open and the other FTP commands.

The normal abort sequence, [CTRL]-C does not work during a transfer.

Configuration and Startup

The FTP Client requires the following:

pSH starts FTP Client by calling ftp_main(). The pSOSystem operating system includes a pre-configured version of pSH and FTP Client, but to add FTP Client to pSH, an entry for it must be made in the pSH list of user applications. The following shows an example of a user application list containing FTP and Telnet:

struct appdata_t appdata[] = {
  { "ftp", "file transfer application", ftp_main, "ft00", 250, 
     4096, 4096,1, 0 },
    { "telnet", "telnet application", telnet_main, "tn00", 250, 
      4096, 4096, 0, 0 },
   { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

You can define the other elements in the preceding example ("ft00", and so on).

FTP Commands

The following commands can be entered at the FTP prompt (ftp>). File naming conventions and descriptions of transfer parameters follow these command descriptions.

! [ command ]
Run command as a shell command on the local machine.

account [ passwd ]
Provide a supplemental password required by a remote system for access to resources after a successful login. If no argument is included, you are prompted for an account password in a non-echoing input mode.

append local_file [remote_file]
Append a local file to a file on the remote machine. If remote_file is unspecified, the local filename is used to name the remote file. File transfer uses the current settings for representation type, file structure, and transfer mode.

ascii
Set the representation type to network ASCII (the default type).

bell
Sound a bell after each file transfer command completes.

binary
Set the representation type to image.

bye
Terminate the FTP session to the remote server and exit FTP. An EOF also terminates the session and causes an exit.

cd remote_directory
Change the working directory on the remote machine to remote_directory.

cdup
Change the working directory on the remote machine to the parent of the current working directory on the remote machine.

close
Terminate the FTP session with the remote server and return to the command interpreter.

cr
Toggle [RETURN] stripping during network ASCII-type file retrieval. Records are denoted by a [RETURN] or [LINEFEED] sequence during a network ASCII-type file transfer. When cr is on (the default), [RETURN] characters are stripped from this sequence to conform to the UNIX system single-LINEFEED record delimiter. Records on non-UNIX system remote hosts may contain single [LINEFEED] characters; when a network ASCII-type transfer is made, the [LINEFEED] characters can be distinguished from a record delimiter only when cr is off.

delete remote_file
Delete the file remote_file on the remote machine.

dir [ remote_directory ] [ local_file ]
Print a listing of the directory contents in the directory, the remote directory, and, optionally, the local file. If no directory is specified, the current working directory on the remote machine is used. If no local file is specified or if the local file is specified by a dash (-), output goes to the terminal.

disconnect
Synonymous to close

get remote_file [ local_file ]
Retrieve the remote file and store it on the local machine. If the local filename is not specified, it receives the same name it has on the remote machine. When no name is specified, the program-generated name can be altered because of the current case, ntrans, and nmap settings. The current settings for representation type, file structure, and transfer mode apply during file transfers.

glob
Toggle globbing (filename expansion) for mdelete, mget and mput. If globbing is off, filenames are taken literally.

Globbing for mput is done the same as with the csh UNIX command. For mdelete and mget, each remote filename is expanded separately on the remote machine, and the lists are not merged.

Expansion of a directory name is likely to be very different from expansion of the name of an ordinary file: the exact result depends on the remote operating system and FTP server. The result can be previewed by executing the following:
mls   remote _files   -
The mget and mput commands are not meant to transfer entire directory subtrees of files: instead, transfer directory subtrees of files by transferring a tar (UNIX command) archive of the subtree (using the image representation type as set by the binary command).

hash
Toggle hash-sign (#) printing for each data block transferred.

help [ command ]
Print information about the command. With no argument, ftp lists the known commands.

lcd [ directory ]
Change the working directory on the local machine. If no directory is specified, the user's home directory is used.

ls [ remote_directory ] [ local_file ]
Print a listing of the contents of a directory on the remote machine. If remote_directory is unspecified, the current working directory is used. If no local file is specified or if local_file is a dash (-), the output goes to the terminal.

mdelete [ remote_files ]
Delete the specified remote_files on the remote machine.

mdir remote_files local_file
The mdir command is like dir, except that mdir supports specification of multiple remote files. If interactive prompting is on, ftp prompts you to verify that the last argument is the local file targeted to receive mdir output.

mget remote_files
Expand the remote_files on the remote machine and execute a get for each filename thus produced. See glob for details the filename expansion. Resulting filenames are then processed according to case, ntrans, and nmap settings. Files are transferred into the local working directory, which can be changed by executing lcd directory. New local directories can be created with !mkdir directory.

mkdir [directory_name]
Make a directory on the remote machine.

mls remote_files local_file
The mls command resembles ls(1V), except that mls supports specification of multiple remote files. If interactive prompting is on, ftp prompts you to verify that the last argument is the local file targeted to receive mls output.

mode [ mode_name ]
Set the transfer mode to mode_name. The only valid mode name is stream, which corresponds to the default stream mode.

mput local_files
Expand wild cards in the list of local files given as arguments and do a put for each file in the resulting list. See glob for details on filename expansion.

nlist [ remote_directory ] [ local_file ]
Print an abbreviated listing of the contents of a directory on the remote machine. If remote_directory is unspecified, the current working directory is used. If no local file is specified or if local_file is a dash (-), the output goes to the terminal.

open host [ port ]
Establish a connection to the specified host FTP server. A port number is optional. If port is specified, ftp attempts to contact an FTP server at that port. If the auto-login option is on (the default), ftp also attempts to automatically log the user into the FTP server (refer to the description of user).

prompt
Toggle interactive prompting. Interactive prompting during multiple file transfers allows you to selectively retrieve or store files. Prompting is on by default. If prompting is off, an mget or mput transfers all files, and an mdelete deletes all files.

put local_file [ remote_file ]
Store a local file on the remote machine. If remote_file is unspecified, the local filename is used to specify the remote file. File transfer uses the current settings for representation type, file structure, and transfer mode.

pwd
Print the name of the current working directory on the remote machine.

quit
Synonymous to bye.

quote arg1 arg2 ...
Send the arguments specified verbatim to the remote FTP server. A single FTP reply code is expected.

recv remote_file [ local_file ]
Synonymous to get.

remotehelp [ command_name ]
Request help from the remote FTP server. If a command_name is specified, it also goes to the server.

rename from to
Rename the file specified by from on the remote machine to have the name specified by to.

reset
Clear reply queue. This command synchronizes command/reply sequencing with the remote FTP server. Synchronization may be necessary if the remote server violates FTP protocol.

rmdir directory_name
Delete a directory on the remote machine.

runique
Toggle storing of files on the local system with unique filenames. The generated unique filename is reported. The runique command does not affect local files generated from a shell command. By default runique is OFF.

If a file already exists with the same name as the target local filename for a get or mget, a .1 is appended to the name. If the resulting name matches another existing filename, a .2 is appended to the original name. If the additions reach .99, an error message is printed, and the transfer does not take place.

send local_file [ remote_file ]
Synonymous to put.

sendport
Toggle the use of PORT commands. By default, ftp attempts to use a PORT command when it establishes a connection for each data transfer. The use of PORT commands can prevent delays during multiple file transfers. If the PORT command fails, ftp uses the default data port. When the use of PORT commands is disabled, no attempt is made to use PORT commands for each data transfer. This is useful for certain FTP implementations that ignore PORT commands but incorrectly indicate they have been accepted.

status
Show the current status of FTP.

sunique
A toggle for storing of files on a remote machine under unique filenames. For successful file storage, the remote FTP server must support the STOU command. The remote server reports the unique name. The default state is OFF.

tenex
Set the representation type to the value needed for communication with TENEX machines.

type [ type_name ]
Set the representation type to type_name. Valid type names are as follows:

ascii for network ASCII

binary or image for image

tenex for local byte size of eight bits (used to talk to TENEX machines).

If no type is specified, the current type is printed. The default type is network ASCII.

user username [ password ] [ account ]
Identify the user to the remote FTP server. If the password is not specified and the server requires it, ftp prompts for the password after it disables local echo. If an account field is unspecified and the FTP server requires one, the user prompts for an account field.

If the remote server does not require an account input for login and if it is nevertheless specified, an account command is relayed to the remote server after the login sequence is completed. Unless ftp is invoked with auto-login disabled, this process is done automatically upon initial connection to the FTP server.

verbose
Toggle verbose mode. In verbose mode, all responses from the FTP server are displayed to the user. If verbose mode is on, statistics about the efficiency of the transfer are reported when a file transfer completes. By default, verbose mode is on if FTP commands come from a terminal (and off otherwise).

? [ command ]
Synonymous to help.

A command argument can have embedded spaces if the argument is enclosed in quote marks (").

If a required command argument is absent, ftp prompts for that argument.

File Naming Conventions for FTP Command Arguments

Arguments for some commands in the preceding list can be local files. Local files specified as arguments to FTP commands are processed according to the following rules:

File Transfer Parameters

FTP command specification (described in the preceding pages) includes three parameters that can affect a file transfer. The three parameters are the representation type, the file structure, and the transfer mode. The representation type can be one of the following:

The network ASCII and EBCDIC types also have a subtype. This subtype specifies whether vertical format control ([NEWLINE] characters, form feeds, and so on) are to be processed in one of the following ways:

FTP supports the network ASCII (subtype non-print only) and image types.

Next, the file structure can be one of file (no record structure), record, or page. FTP supports only file.

Lastly, the transfer mode can be either stream, block, or compressed. FTP supports only stream.

FTP Client Bugs

Correct execution of many commands depends on correct operation by the remote server. An error in the treatment of carriage returns in the 4.2 BSD code handling transfers with a representation type of network ASCII has been corrected. This correction can result in incorrect transfers of binary files to and from 4.2 BSD servers using a representation type of network ASCII. Avoid this problem by using the image type.

NAME

FTP Server - Allow remote systems running FTP to transfer files to/from a pHILE+ device

DESCRIPTION

FTP Server allows remote systems that are running the ARPANET File Transfer Protocol to transfer files to and from a pHILE+ device. FTP Server is implemented as a daemon task named ftpd. The ftpd daemon listens for connection requests from clients and creates server tasks for each FTP session that a client establishes.

Configuration and Startup

FTP Server requires the following:

The user-supplied FTP Server Configuration Table defines application-specific parameters, and the following is a template for this table. This template exists in the include/netutils.h file.

struct ftpcfg_t {
        long task_prio;        /* priority for ftpd task */
     long max_sessions;     /* max # of concurrent sessions */
       char *vol_name;        /* name of the login volume */
   char **hlist;  /* list of trusted clients */
    struct ulist_t *ulist; /* list of permitted users */
    long reserved[2];      /* must be 0 */
};

Definitions for the FTP Server Configuration Table entries are as follows:

task_prio
defines the priority at which the daemon task ftpd starts executing.

max_sessions
defines the maximum number of concurrently open sessions.

vol_name
defines the name of the volume to use when a client logs into the pSOSystem environment.

hlist
contains a pointer to a list of the IP addresses of the trusted clients. If this field is 0, FTP Server accepts a connection from any client.

ulist
points to a list of structures that contain login information of permitted users. If this field is 0, all users are allowed to log in. The following is a template for one of these structures:
struct ulist_t {
        char *login_name;       /* user name */
 char *login_passwd;     /* user password */
     long reserved[4];       /* must be 0 */
};

The following is an example structure with three entries:
struct ulist_t ulist[] {
        { "guest", "psos0", 0, 0, 0, 0 },
       { "scg",   "andy0", 0, 0, 0, 0 },
       { 0,       0,       0, 0, 0, 0 }
}

reserved
reserved for future use, and each must be 0.

FTP Server comes as one object module and must be linked with a user application. Calling the function ftpd_start(ftpdcfg) at any time after pSOSystem initialization (when ROOT is called) starts it. The parameter ftpdcfg is a pointer to the FTP Server Configuration Table. If FTP Server starts successfully, ftpd_start() returns 0, otherwise it returns a non-zero value.

EXAMPLE

The following code fragment shows an example configuration table and the call that starts FTP Server. The complete example code exists in the apps/netutils/root.c file.

#include <netutils.h>
start_ftp_server() {
       /* FTP server configuration table */
    static ftpcfg_t ftpcfg =
        {
       250,    /* priority for ftpd task */
    4,      /* max # of concurrent sessions */
      "4.0",  /* name of the login volume */
  0,      /* list of trusted clients */
   0,      /* list of permitted users */
   0, 0    /* must be 0 */
 };
      /* start the FTP server */
      if (ftpd_start(&ftpcfg))
        printf("ftpd_start: failed to start\n");
}

NAME

Loader - Allow run-time target loading and unloading of application programs

DESCRIPTION

The pSOSystem loader provides a programmatic interface for controlling run-time target loading and unloading of application programs from a variety of I/O interfaces. The loader is supplied as a library of functions that can be called from a user application.

Powerful loader applications can be written using just three functions (load, unload, and release). The loader library has been designed to depend only on pSOS+ system services; it does not depend on any other components. However, you may need to include other components like the pHILE+ file system manager and the pNA+ network manager, depending on the type of I/O interface being used to load applications.

The loader supports the loading of object files residing on pHILE+ media (pHILE+ volumes, MS-DOS volumes, or remote file systems mounted through NFS). The loader also supports loading from any device driver that conforms to the interface standard defined by the pREPC+ library. Additional requirements for device drivers are described in ``Interfaces and Drivers.'' A pseudo device driver that uses TFTP (Trivial File Transfer Protocol) to transfer files from a remote host is also provided with the pSOSystem operating system. You can use the TFTP device driver in conjunction with the loader.

The loader can load object files that are either in Motorola S-record (SREC) format or in the ELF format generated by pRISM compiler tools. The following types of object files are supported by the loader:

The term relocatable refers to object files that contain relocation information. Such object files are produced as intermediate files during the compilation/linking process. The relocatable object (.o) files are produced by various pRISM tools, as follows:

The ability to load relocatable files with the loader provides extra flexibility. For example, you can generate position-dependent code but defer the decision of where to place the code in target memory until runtime. However, note that relocatable files must not contain unresolved external symbol references.

Host Installation and Configuration

The loader should be installed under the pSOSystem directory structure. Upon successful installation, the following files and directories are created under the pSOSystem root directory:

sys/libc/loader.olb
is the Green Hills library file containing the loader.

include/loader.h
is the header file that contains typedefs, defines, and function prototypes for the functions provided in the loader library.

configs/std/ldcfg.c
is the configuration file for customizing the loader. It controls what modules get linked with the user loader application.

apps/loader/README
contains detailed on-line instructions for generating and running a sample loader application.

apps/loader/default.bld
contains the rules to build a sample loader application and is used by the pRISM build environment.

apps/loader/userapp.bld
contains the rules to build a sample loader application and is used by the pRISM build environment.

apps/loader/sys_conf.h
is the pSOSystem configuration file.

apps/loader/*.[csh]
are source programs for the sample application demonstrating how to use loader functions in applications. To run this sample application, you may need to configure the pREPC+, pHILE+, pRPC+, and pNA+ components, and/or the TFTP pseudo device driver in the system.

apps/loader/loadable/*
are source files for a simple pSOSystem application that is intended to be loaded by the sample loader application.

configs/std/appi.bld
is a system build file for generating position-independent loadable applications.

configs/std/appre.bld
is a system build file for generating relocatable loadable applications.

configs/std/appabs.bld
is a system build file for generating absolute loadable applications.

configs/std/beginapi.s
is the application startup file for use by position independent loadable applications (similar to the begina.s file provided with pSOSystem).

The loader contains two user-configurable modules. One supports the loading of Motorola S-records and the other supports the loading of ELF object files. It is possible to generate a loader application that contains any one or both of the modules. By default, both of the modules are enabled. The apps/loader/sys_conf.h file contains the following two #defines:

#define LD_SREC_MODULE YES    /* Motorola S-record support */
#define LD_ELF _MODULE YES    /* ELF support */

To exclude a particular module from getting linked to the loader application, change YES to NO for the module you want to exclude.

sys_conf.h also contains the following #define, which determines the maximum number of loading operations that can be handled simultaneously by the code in the loader library:

#define LD_MAX_LOAD 8    /* Max number of simultaneously active load */

You must make any necessary changes to LD_SREC_MODULE, LD_ELF_MODULE, or LD_MAX_LOAD by modifying sys_conf.h before generating the loader application.

In addition to the files listed above, a host-level utility called ld_prep gets installed under the various bin/<host> subdirectories in the pSOSystem directory tree. You must include the proper subdirectory in your PATH, depending on the host environment you are using for pSOSystem application development.

For example, if using a Sun SPARCstation as the development platform, modify your path as follows:

set path = ( $path $PSS_ROOT/bin/sparc ) # if csh is the working shell

or

PATH=$PATH:$PSS_ROOT/bin/sparc  # if sh or ksh is the working shell

where PSS_ROOT is an environment variable specifying the pathname of the pSOSystem root directory.

After installation, copy the files under the apps/loader directory to a working directory of your choice before making any modifications or generating the sample application. (The UNIX cp -r or MS-DOS xcopy commands can be used for this purpose.) The README file contains detailed information about the sample application. It also contains instructions for generating and running this application. You must follow these instructions to compile and run the sample loader application. Run this application and play around with the sample code to help familiarize yourself with the loader.

Concepts and Operation

The loader is useful in situations where you are dealing with multiple applications (running simultaneously on a target), and they can be partitioned so that no two applications share symbol references with each other. There can be many reasons for partitioning applications into multiple executable files and/or using dynamic loading. Some of these are as follows:

Typically, you will make the loader run as part of the root task. This task remains resident on the target and loads other applications as and when needed. This is one of the suggested approaches and, as demonstrated by some of the sample applications, the loader functions can be used in many other ways.

For ease of explanation, assume the presence of a single task called the loader task, which takes care of loading other application tasks, called loadable applications. The loader task is linked with the pSOSystem operating system and gets loaded on the target system using the standard method for bootstrapping the system. First, an outline is provided of a simple method for writing the loader task using the functions provided by the loader library, loader.olb.

The load() function is provided for loading loadable applications. These applications may remain resident on the target forever, or only temporarily. Loadable applications can be unloaded using the unload() function. A call to unload() frees up any memory allocated by load() for the run-time image of a loadable application; it also frees up any state information associated with the loadable application [saved by the loader library during the call to load()].

If the loadable application is to remain resident on the target forever, the release() function must be called to free up any state information associated with the loadable application. A call to release() does not free up the memory occupied by the run-time image of the loadable application, and the application can keep running without any hindrance. A detailed description of these functions is provided later in this section.

You open the file containing the loadable application using either the pHILE+ open_f() call or the de_open() function, which opens the device driver through which the loadable application will be read. The file descriptor returned by open_f() or the device number of the device driver must be passed to the load() function as the first argument (fd). You must also specify whether the first argument refers to a pHILE+ file descriptor or a device number. This is done by setting either LD_DESC_PHILE or LD_DESC_DEV in the second argument (flags) passed to load().

The load() function reads in the loadable application using either the pHILE+ read_f() function or the de_read() function, whatever the case may be. It determines the object file format of the loadable application and invokes the appropriate module (SREC or ELF ) to convert the object file into a binary image suitable for execution. The exact behavior of load() depends on the type of code (position independent, absolute, or relocatable), as follows:

Loading absolute code is a one-step process. Similarly, loading position-independent or relocatable code at the default load address chosen by the loader is also a one-step process. You simply call load() with the LD_LOAD_DEF flag set in the flags argument.

If for some reason you want to control where the various parts (sections) of an object file get loaded into target memory, a two-step process must be followed:

  1. Call load() with the LD_GET_INFO flag set in the flags argument. The load() function reads in the object file information from the header present therein and returns a pointer to this information in the third argument (of_info) passed to load(). You can modify the load addresses (part of the information returned through of_info) of one or more of the sections.
  2. Call load() again with the LD_LOAD_MOD flag set in the flags argument and with the modified object file information (pointed to by *of_info) passed as the third argument.

Once the load() call returns, you are free to close the object file (or device driver) by calling close_f() (or de_close()). At this point the binary image of the loadable application has been loaded into memory. If the binary image corresponds to a pSOS+ task, you can create and start the task at any time. In most cases, the entry point to the task can be obtained from the object file information returned by load(). If the entry point is not known, it is set to zero by load(). You must call the t_create() and t_start() system services of the pSOS+ kernel with appropriate arguments to create and start the task, respectively.

Once the task is running there are two possibilities, as explained earlier:

The Loader API

Following is a template for the three data structures used by the pSOSystem loader. The first is the OF_INFO structure, a pointer to which is returned by load() and also gets passed to unload() and release(). The second is the SECN_INFO structure, which is contained in the OF_INFO structure. The third is the TASK_INFO structure, which is also contained in the OF_INFO structure. These structures are defined in the <include/loader.h> file.

typedef struct OF_INFO{ 
        int desc;       /* Object file descriptor */
    char format[5]; /* Object file format */
        char code_type; /* Code Type (Absolute/Relocatable/PIC) */
      int nsecns;     /* Number of sections */
        SECN_INFO *secn_info;   /* Section information */
       TASK_INFO  task_info;   /* Info needed to create & start task */
} OF_INFO;

format
is a four-character null-terminated string that identifies the object file format of the file loaded by the loader. The values returned in this field are SREC or ELF, which correspond to Motorola S-record or ELF formats, respectively.

code_type
can take one of three values: LD_ABSOLUTE, LD_RELOCATABLE, or LD_PIC. LD_ABSOLUTE implies that the code is position dependent. LD_RELOCATABLE implies that the object file contains relocation information and can be loaded anywhere in target memory. LP_PIC implies that the code is position independent.

nsecns
tells the number of independently loadable sections of the object file. A file in SREC format always has one section.

secn_info
points to an array of SECN_INFO structures that has nsecns elements. As described below, the SECN_INFO structure contains information regarding each of the separately loadable sections of the object file.

task_info
is a structure of type TASK_INFO. The information contained herein may be used by the loader to create and start the task, once the loader has loaded the object file into target memory.

desc
is used by the loader to identify the loaded object file, and you must not modify it. The other fields are also read-only in nature but are ignored by the loader if they are modified in between two loader calls.

The second structure, SECN_INFO, contains information regarding the individually loadable sections of an object file and is defined as follows:

typedef struct secn_info{
       char name[LD_SECNAMELEN];       /* Name of the section */
       unsigned long type;     /* Type of the section */
       unsigned long size;     /* Size of the section */
       unsigned long base;     /* Section load address */
} SECN_INFO;

The name and type field describe the name and type of the section, respectively. These fields are compiler dependent and are supplied only for your information. The loader does not make use of these fields. The size field specifies the size of the section in bytes, and base specifies the address in memory where this section gets loaded.

You can modify base, as explained in the description of the load() function later in this section, to control the placement of the section in memory if the code_type is LD_RELOCATABLE. Modifications done to any other fields of this structure in between any two loader calls are ignored by the loader.

The third structure, TASK_INFO, contains information necessary to create and start a task using the pSOS+ t_create() and t_start() system services. This information is obtained from the object file by load() and can be stored in the object file by running ld_prep on the object file and specifying the appropriate values for various task-specific parameters (see the man page for ld_prep for further details). TASK_INFO is defined as follows:

typedef struct task_info{
       char name[4];   /* Name of the task to be created */
    unsigned long priority; /* Task priority */
     unsigned long sstack_sz;        /* Supervisor stack size */
     unsigned long ustack_sz;        /* User stack size */
   unsigned long create_flags;     /* Flags used by t_create() */
  unsigned long start_mode;       /* Mode used by t_start() */
    void   (*entry) ();     /* Task entry point */
} TASK_INFO;

name
is the four-character name of the task passed to t_create().

priority
is the starting priority of the task passed to t_create().

sstack_sz
is the size of the supervisor stack (in bytes) passed to t_create().

ustack_sz
is the size of the user stack (in bytes) passed to t_create().

create_flags
are the flags passed to t_create().

start_mode
is the mode passed to t_start().

entry
is the entry point, if any, for the task passed to t_start().

The load() Function

load() is defined as follows:

        #include <loader.h>
     unsigned long load (
            unsigned long   fd,
             unsigned long   flags,
          OF_INFO **of_info
       );

load() reads an object file from an open file descriptor fd and converts the incoming stream of data into a binary image ready for execution. The information about the object file is read and a pointer to it is returned in the location pointed by of_info. The fd is either a file descriptor returned by a call to the pHILE+ open_f() routine or it is the device number of a pREPC+-compatible device driver. You must set the LD_DESC_PHILE or LD_DESC_DEV fields in the flags argument to specify whether fd is a file descriptor returned by open_f() or a device number.

The exact behavior of load() is controlled by the load type specified by the flags argument. You can specify one of three load types (LD_GET_INFO, LD_LOAD_DEF, LD_LOAD_MOD) by bitwise OR-ing one of the three values in the flags argument.

If LD_LOAD_DEF is specified, load() reads the object file and loads the binary image into target memory, using the default load address specified by the object file header. The values used to load the file are stored in an OF_INFO structure, and a pointer to this structure is returned through of_info.

If LD_GET_INFO is specified, load() reads the object file header information and returns a pointer to it through of_info. No binary image of the object file is loaded in target memory.

You can modify certain values returned in the OF_INFO structure and call load() to load the binary image by specifying the load type as LD_LOAD_MOD.

load() can handle both absolute and relocatable object files. The term relocatable also covers the position-independent code generated by Green Hills compiler tools.

If the object file is absolute, it is always loaded at the address specified by the object file header, and you may not be able to modify these values. Also, it is assumed that it is safe to load an absolute object file at the address specified by the object file header. If the object file is relocatable, then the memory needed to load the object file is automatically allocated by load().

However, for relocatable object files, you can control the loading of file on a per-section basis by modifying the relevant fields in the OF_INFO structure returned by calling load() with load type LD_GET_INFO and then passing the modified structure to load() with load type LD_LOAD_MOD.

On success, load() returns 0; otherwise, it returns a non-zero error number.

The following errors are returned by load():

ERR_SYNTAX
The loader encountered a syntactic construct in the object file that is not understood by the loader.

ERR_INVAL
An invalid operation was attempted (like trying to call load() with flags LD_LOAD_MOD without previously calling load() with flags LD_GET_INFO). Also, this error is returned if the desc field of of_info is invalid, or an invalid flag is specified.

ERR_NO_OFM
The format of the object file being loaded is not supported by the loader.

ERR_OFM_FULL
An attempt was made to load an object file while the configured maximum number of files has already been loaded and has neither been released nor unloaded.

ERR_UNSUPP
The object file being loaded contains some unsupported feature (like an ELF relocatable file containing unresolved externals).

ERR_NOT_EXEC
The object file did not compile properly and is not ready for execution.

ERR_INTERNAL
The loader discovers an inconsistency in the internal data structures.

ERR_TOOBIG
One of the sections of the file being loaded is too big to fit in the memory.

ERR_NOSEG
The object file (or a part thereof) cannot be loaded because of a temporary shortage of memory.

Other errors may be returned due to the failure of either a pSOS+ system call or a call made internally by the loader to the pHILE+ file system manager or a device driver.

CAUTION:
When calling load() with flags LD_GET_INFO or LD_LOAD_DEF, you must not allocate memory for the of_info structure, as this is done by load(). The proper way of calling load() is as follows:
        #include <loader.h>
     OF_INFO *my_of_info;
    unsigned long fd, flags;
                ...
             ...
     load (fd, flags, &my_of_info);
          ...
             ...

The unload() Function

unload() is defined as follows:

        #include <loader.h>
     unsigned long unload (
          OF_INFO *of_info
        );

This function unloads an executable file image from the target memory, where it was loaded previously using load(). of_info points to the object file information returned by a previous call to load().

If the type of executable being unloaded is LD_ABSOLUTE, the unload() function does nothing to free the memory associated with the executable - it is the responsibility of the caller to free up the memory (if any) that it allocated previously.

If the type of executable is LD_RELOCATABLE, this function frees up any memory allocated earlier for loading the executable. However, it does not free any memory for sections of executable files that were allocated by the caller. Those must be taken care of by the caller.

unload() frees up any state information associated with of_info and preserved internally by the loader. It also frees up the object file information pointed to by of_info, and it must not be referred to subsequently by the caller.

The unload() function must be called only after the task(s) associated with the loaded executable have been deleted, since all of the memory allocated to load executable code and data is returned to the free storage pool by unload() and can be re-used for any purpose at any time.

On success, unload() returns 0; otherwise, it returns a non-zero error number.

The following errors are returned by unload():

ERR_INVALID
The desc field of of_info is invalid. or you tried to unload an executable that has never been loaded.

Other errors may be returned that can be due to the failure of a pSOS+ system call made internally by the loader.

The release() Function

release() is defined as follows:

        #include <loader.h>
     unsigned long release (
         OF_INFO *of_info
        );

This function frees up the object file information pointed to by of_info, and also any state information associated with of_info and preserved internally by the loader. It must be called in one of the following situations:

The object file information pointed to by of_info must not be referred to subsequently by the caller.

On success, release() returns 0; otherwise, it returns a non-zero error number.

The following errors are returned by release():

ERR_INVALID
The desc field of of_info is invalid, or you tried to release a stale of_info.

Other errors may be returned that can be due to the failure of a pSOS+ system call made internally by the loader.

The ld_prep Utility

The syntax for ld_prep is as follows:

        ld_prep  {-a|-i|-r}  [-v]  [-d defaults_file ]  [-n task_name ]
         [-p priority ]  [-c create_flags ]  [-m task_mode ] 
            [-e entry_point ] [-s supv_stack_size ] 
                [-u user_stack_size ] [-o out_file ]  in_file

ld_prep is a post-processor that must be run on an object file in_file before it can be loaded by the pSOSystem loader. The object file can be in either Motorola SREC format or ELF format. ld_prep analyzes the input object file, prepends a header to it, and writes the file to a user-specified output file out_file (or to a file out.ld by default). The header contains certain information about the object file that is used by the loader.

You must specify whether the input object file has to be loaded at the absolute address specified at link time or whether it can be relocated by the loader to any address of its choosing. You must specify whether the input object file is absolute or relocatable.

Additionally, if the file being loaded corresponds to a task that will be created and started eventually by the user, it is possible to specify all of the task-specific information using ld_prep. This information is passed to the loader application via the TASK_INFO sub-structure of the OF_INFO structure, the pointer to which is returned by load(). This information typically consists of the task name, the priority at which it runs, the sizes of the user and supervisor stacks, the task entry point, and various other task attributes that get passed to t_create() and tstart().

You must run ld_prep on an object file that needs to be loaded by the loader or else an error will be flagged by the loader at runtime.

The following options are provided:

-a
specifies that the input object file is absolute.

-i
specifies that the input object is position independent

-r
specifies that the input object file is relocatable.

-v
specifies the verbose option. Some useful information about the file is printed on stdout.

-d defaults_file
specifies the name of the file from which the defaults must be picked up for options not specified on the command line. The defaults_file must have one or more lines containing the options as they are specified on the command line. A sample defaults_file is shown in the examples.

-n task_name
specifies the user-assigned name of the task. If this option is omitted, the task name is set to LDBL.

-p priority
specifies the task's initial priority within the range 1 to 255. If this option is omitted, the priority is set to 0.

-c create_flags
specifies the flags that get passed to t_create(). The flags can be one or both of G and F.

The G flag specifies that the task is global and addressable by external tasks residing on other nodes. If this flag is omitted, the task is assumed to be local.

The F flag specifies that the task uses floating point units. If this flag is omitted, the task is assumed not to use floating point units.

-m task_mode
specifies the task mode that gets passed to t_start(). The mode can be one or more of A, N, T, and S.

If you specify a defaults file using the -d option, it is parsed first to pick up the defaults. Next, ld_prep parses any command line options. Options specified on the command line override values specified in the defaults file

In most cases, when an option is specified neither in the defaults file nor on the command line, the corresponding parameter is set to 0. When detecting the 0 values, the loader application must determine the appropriate values to use. Note that you must specify either the -a or -r option, either in the defaults file or on the command line; otherwise, an error is flagged by ld_prep.

ld_prep exits with status 0 upon successful execution; otherwise, it exits with exit status 1 and an error message is printed to stderr. The error messages are self explanatory.

Examples

ld_prep -r -o app.ld app.x
ld_prep -a -v -p 180 -n NApp -cF -mAT -e 0x3c0000 -s 512 -o napp.ld newapp.x

is the same as

ld_prep -d task.defs -o napp.ld newapp.hex

where the file task.defs contains the following line:

-a -v -p 180 -n NApp -cF -mAT -e 0x3c0000 -s 512 -o app.ld

Note that a command line option overrides the options specified in the defaults file (-o in the above example).

Warnings

If an option is specified more than once on the command line, the last (rightmost) such definition takes precedence over any previous definition. However, if an option is specified more than once in the defaults file, the behavior of ld_prep is undefined.

A warning is issued if the defaults file contains the -d option and the option is ignored.

Supported Platforms

The ld_prep utility is provided for Sun SPARCstations and machines running MS-DOS.

Compiling and Running Applications Using the pSOSystem Loader

The procedure for compiling and running applications using the loader is as follows:

  1. Write the loader task, then compile and link it with the loader library and the pSOSystem operating system to generate the ram.hex file.
  2. Next, decide whether to use the SREC format or the ELF format for the applications that get loaded through the loader task. The SREC format must be chosen if you are generating position-independent code or if the application's location in target memory can be determined at compile time. The ELF format must be chosen when it is not possible to determine at compile-time where the application gets loaded in target memory. The ELF can be chosen under the other two situations, also.
  3. Use the standard pSOSystem configuration files and build files, or use the configuration files and build files provided with the sample loader, to generate app.hex (the SREC version) or app.cfe (the ELF version) files for the application task, which are to be loaded with the loader.
  4. Run the ld_prep utility with app.hex (or app.cfe) as the input file. On the ld_prep command line, specify the entry point, the code type (relocatable/absolute/pic), and any other parameters that may be appropriate. A file out.ld will be generated, by default, in the current working directory. If you want, you can specify a name of your choice (instead of out.ld) using the -o command-line option to ld_prep.
  5. Copy the file produced in Step 4 to the appropriate directory from where the loader has been programmed to load this application. For example, you may need to copy this file to the /tftpboot directory on certain host systems that provide a restricted TFTP facility, and from which the TFTP pseudo driver is being used by the loader task to load applications.
  6. Using the bootstrap loader on the target, load the ram.hex file generated in Step 1 and restart the pSOSystem operating system. If the loader task is running, you should be able to load your application.

Guidelines for Writing Device Drivers

As stated earlier, a device driver that interfaces with the loader must meet the interface requirements set by the pREPC+ library. See the guidelines for writing device drivers in Section 3, ``Interfaces and Drivers.'' The loader calls only the de_read() function internally. It passes an I/O parameter block with the following format:

."typedef struct {
      unsigned long count;   /* Number of bytes to read */
    void  *address;        /* Address of data buffer */
} iopb;

The loader needs the device driver to be capable of skipping data (i.e. seeking in the forward direction). To seek in the forward direction, the loader calls de_read() with the count field in the iopb structure set to the number of bytes to skip, and with the address field in the iopb structure set to (void *)NULL.

The device driver read function, on receipt of an iopb structure with address field set to NULL, reads count number of bytes from the device and discards those. Thus, this case is treated the same as any other case, except that the driver does not copy the data. This is the only additional requirement set by the loader, and it is very easy to implement. For example, you can refer to the TFTP pseudo device driver sources that are provided with the pSOSystem operating system in the drivers directory.

NAME

NFS Server - Allow systems to share files in a networked environment

DESCRIPTION

NFS Server allows systems to share files in a networked environment. It permits NFS clients to read and write files transparently on pSOSystem disks that the pHILE+ file system manager manages.

NFS Server is implemented as two application daemon tasks. The mntd task is the mount daemon. It processes requests for mounting and listing exported directories. The nfsd task processes all other NFS requests after exported directories have been mounted.

Configuration and Startup

NFS Server requires:

The user-supplied NFS Server Configuration Table defines application-specific parameters. A template for this configuration table (shown below) exists in the include/netutils.h file.

struct nfscfg_t 
{
       long task_prio; /* priority for nfsd task */
    long unix_auth; /* UNIX authentication-required flag */
 long error_opt; /* error reporting option */
    long vol_blksize;       /* system-wide volume block size */
     char *def_vol_name;     /* name of the default volume */
        nfselist_t *elist;      /* ptr to the list of exported directories */
   long reserved[4];       /* must be zero */
};

Definitions for the NFS Server Configuration Table entries are as follows:

task_prio
defines the initial priority of the daemon tasks mntd and nfsd.

unix_auth
determines if client authorization is checked. If unix_auth equals 1 (TRUE), NFS Server checks a client's UNIX ID for the value 0 (indicating a root client) before mounting. If unix_auth equals 0 (FALSE), any client on a trusted machine can mount any of the exported directories.

error_opt
relates to error response. If error_opt equals 1 (TRUE), NFS Server returns the appropriate error status on operations that attempt to modify file attributes. If error_opt equals 0 (FALSE), NFS Server returns ok even if the requested operation did not happen. This allows UNIX utilities that modify file attributes to operate on pHILE+ files even when the pHILE+ file system manager does not behave exactly the same as UNIX.

vol_blksize
defines the system-wide block size of the volumes that the pHILE+ file system manager manages. The system-wide block size must match the size defined by the pHILE+ Configuration Table entry fc_logbsize. However, the notation for the vol_blksize value differs from that of fc_logbsize, as follows: vol_blksize is specified as the actual block size, and fc_logbsize is specified as the exponent of 2 for the block size. For example, if vol_blksize is 512 bytes, then fc_logbsize is 9 (29 = 512).

def_vol_name
defines the name of the default volume to use when a client issues a mount request without specifying a volume name.

elist
points to a structure. The structure contains a list of exported directories and trusted clients. If elist equals 0, NFS Server looks for the export information in the /etc/exports file on the default pHILE+ volume (defined by def_vol_name). If no such file exists, NFS Server assumes everything in the system is exportable and accepts all mount requests. When elist is specified, its structure must be as follows:
struct nfselist_t
{
      char *dir_path; /* export list */
       char *hlist;    /* list of trusted clients*/
};

The following is an example of an export list with three entries:
struct nfselist_t nfselist[] =
{
 {"4.0/", "000.000.00.000", 000.000.00.000"},
    {"5.0/etc", 0 },
        {0, 0}
};

where the first entry permits the client machines with IP addresses 000.000.00.000 and 000.000.00.000 to mount on the root directory / on volume 4.0. The second entry allows any client to mount on directory etc on volume 5.0. The last entry defines the end of the export list.

reserved
reserved for future use, and each must be 0.

NFS Server comes as one object module and must be linked with a user application. Calling the function nfsd_start(nfscfg) any time after pSOSystem initialization (by calling ROOT) starts NFS Server. The parameter nfscfg points to the NFS Server Configuration Table. If NFS Server is started successfully, nfsd_start() returns 0.

EXAMPLE

The following code fragment shows an example configuration table and the call that starts NFS Server. The complete example code exists in the apps/netutils/root.c file.

#include <netutils.h>
start_nfs_server()
{
/* NFS server configuration table */
static nfscfg_t nfscfg = 
   {
       250,    /* task priority for nfsd task */
       1,      /* requires "root" UNIX client to mount */
      0,      /* no error reporting */
        512,    /* system-wide volume block size */
     "4.0",  /* default volume name */
       0,      /* everything exported */
       0, 0, 0, 0      /* zeros for all reserved entries */
    };
/* start the NFS server */
if (nfsd_start(&nfscfg))
    printf("nfsd_start: failed to start\n");
}

The following features are not supported in the current version:

On the other hand, the following parameters do apply:

NAME

pSH - Interactive command line shell

DESCRIPTION

pSH provides an interactive, command line shell. pSH consists of two parts:

pSH is provided as part of the system utilities object library (sys/libc/netutils.lib). pSH contains a set of built-in commands. Commands or complete applications that will be spawned as separate tasks can be added to pSH.

Configuration And Startup

pSH requires the following components:

The user-supplied pSH Configuration Table defines application-specific parameters. The following is a template for this configuration table. The template exists in the file include/netutils.h:

struct pshcfg_t {
       long flag;      /* services options */
  long task_prio; /* priority for each shell task */
      char *def_vol_name;     /* default login volume name */
 struct ulist_t *ulist;  /* list of permitted users */
   appdata_t *app; /* ptr to the list of user apps */
      cmddata_t *cmd; /* ptr to the list of user cmds */
      long reserved[4];       /* must be 0 */
};

Definitions of the pSH Configuration Table entries are as follows:

flag
specifies which services to provide. If this field is 1, only the part of pSH that serves the console login is activated. If this field is 2, only the part of pSH that serves Telnet logins is activated. If flag is neither 1 nor 2, both parts of pSH are activated.

task_prio
defines the priority at which the shell task starts executing.

def_vol_name
names of the default volume to use when a user logs into the pSOSystem environment.

ulist
points to a list of structures. The structures contain login information about permitted users. If this field is 0, any user can log in. The structure format is as follows:
struct ulist_t 
{
        char *login_name;       /* user name */
 char *login_passwd;     /* user password */
     long reserved[4];       /* must be 0 */
};

If ulist is provided, the last structure in the array must be all 0's to indicate the end of the list. The following example defines two users:
struct ulist_t ulist[] = {
      { "guest", "psos0",     0, 0, 0, 0 },
   { "scg",   "andy0",     0, 0, 0, 0 },
   { 0,       0,   0, 0, 0, 0 }
};

app
points to a list of structures. Each of the structures contains information for executing a user application. The app entry allows users to add system applications (FTP, Telnet, and so on) and user-defined applications to the shell. (pSH comes without built-in user applications. The subsection"Adding Applications to pSH" on page -53 tells how to specify user applications.) The structure format is as follows:
struct appdata_t
{
       char  *app_name;        /* application name */
  char  *app_help;        /* help string */
       void  (*app_entry)();   /* entry point */
       char  *app_tname;       /* task name */
 long  app_tprio;        /* task priority */
     long  app_sssize;       /* system stack size */
 long  app_ussize;       /* user stack size */
   short app_reentrant_flag;       /* reentrant flag */
    short app_reentrant_lock;       /* reentrant lock */
    };

The last structure in the array must be all 0`s to indicate the end of the list. The following is an example with two entries:
struct appdata_t appdata[ ] = {
 { "ftp", "file transfer application", ftp_main, 
            "ft00", 250, 2048, 2048,1, 0 },
     { "telnet", "telnet application", telnet_main, "tn00",
      250, 2048, 2048, 0, 0 },
    { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

cmd
points to a list of structures. The structures contain information for executing user commands. pSH comes with a number of built-in commands (such as cd, pwd, ls), and users can add commands. The cmd entry allows users to add commands to the shell. (The subsection ``pSH Built-in Commands'' on page 2-42 describes built-in commands, and ``Adding Commands to pSH'' on page 2-40 explains how to specify user-defined commands to pSH.) The structure format is as follows:
struct cmddata_t {
      char  *cmd_name;        /* command name */
      char  *cmd_help;        /* help string */
       void  (*cmd_entry)();   /* entry point */
       short cmd_reentrant_flag;       /* reentrant flag */
    short cmd_reentrant_lock;       /* reentrant lock */
    };

The last structure in the array must be all 0's to indicate the end of the list. The following is an example with three entries:
struct cmddata_t cmddata[] = {
  { "type", "list content of a file", type_main, 1, 0 },
  { "volume", "show current working volume",
           volume_main, 1, 0 },
       { 0, 0, 0, 0, 0 }
};

reserved
reserved for future use, and each word must be 0.

Making the psh_start(pshcfg) system call from the application starts pSH. The parameter pshcfg is a pointer to the pSH Configuration Table. If pSH is started successfully, psh_start() returns 0; otherwise, it returns a non-zero value.

The pSH configuration table is defined as follows:

struct pshcfg_t {

long flag; /* services options */

long task_prio; /* priority for pshd task */

char *def_vol_name; /* name of the default login volume */

ulist_t *ulist; /* ptr to the list of trusted users */

appdata_t *app; /* ptr to the list of applications */

cmddata_t *cmd; /* ptr to the list of commands */

unsigned long console_dev; /* psh console device number */

long reserved[3]; /* reserved for future use, must be 0 */

};

The following code fragment shows an example configuration table and the call that starts pSH. The complete