Date: Tue, 6 Dec 1994 18:04:02 -0800 From: dmk@hsmpk14a-91 (David Kahn) Subject: Item #215: P215 V1 Extensible Client Services Package #ident "@(#)client-interface 1.3 94/12/02 SMI" Proposal for inclusion in errata/addenda document. Title: P215 V1 Extensible Client Services Package. Date: Nov 30, 1994 Author: David Kahn, Tayfun Kocaoglu, Mitch Bradley Summary: Create a package for the client interface, with new FCodes allowing the client interface to be extended (and accessed) by FCode and other client programs. Stipulate the existence of a package "/openprom/client-services" if the client interface exists. Define that the client interface works by calling the methods in this package. Modify the definition of the FIND-PACKAGE FCode, allowing the package to be located; Create 2 new FCodes: PUSH-PACKAGE and POP-PACKAGE, allowing the client interface to be extended. Finally, create glossary entries for each of the client interface services defined in the core specification. Proposal: Include the following text in the errata/addenda document: 1. Extensible Client Services Package. 1.1. Extensions to Support Packages. The "/openprom" node may have children, but instead of describing a physical bus, this node may serve as a parent node for support packages that are not "opened". Note that packages defined under this node cannot be opened, since the "/openprom" device node does not define an "open" method. Support packages are used by other packages to implement commonly- used functions. With the exception of support packages related to display devices and the "client-services" package, they are located in the "/packages" device node, opened with either OPEN-PACKAGE or $OPEN-PACKAGE, and closed with CLOSE-PACKAGE. Packages that are children of the "/openprom" node may by located with FIND-PACKAGE (as described below) and methods in these packages may be found with FIND-METHOD and the packages may be extended with PUSH-PACKAGE and POP-PACKAGE. 1.1.1. "client-services" Support Package. The "/openprom/client-services" package exists if the implementation includes the Client Interface. The methods included in the package are named identically to each of the client interface services described in the client interface section of the core document and have stack diagrams and behavior as described in the Glossary section of this document. Bindings for specific instruction sets and platform architectures may include additional instruction-set-specific or platform-specific client interface services available to client programs. Those client interface services shall also be defined as methods in this package, if they exist. For compatibility with existing boot firmware, the client program may test for existence of the "/openprom/client-services" device node. IF the device node exists, then the contents of the device node shall comply with this definition. The client-services package includes the following methods as defined in the core specification. Those methods noted as optional in the core specification shall be included only if the given client interface exists. - Client Interface Group: test ( method-cstr -- missing? ) Test for existence of method. - Device Tree Group: peer ( phandle -- sibling-phandle ) Device tree navigation. child ( phandle -- child-phandle ) Device tree navigation. parent ( phandle -- parent-phandle ) Device tree navigation. instance-to-package ( ihandle -- phandle ) Return package handle corr. to given instance. getproplen ( name-cstr phandle -- prop-len ) Get property length getprop ( len addr name-cstr phandle -- size ) Get property value nextprop ( buf-addr prev-cstr phandle -- flag ) Get next property name setprop ( len addr name-cstr phandle -- size ) Set property value canon ( len addr device-cstr -- length ) Fully qualify device specifier. finddevice ( device-cstr -- phandle ) *phandle* of given device spec. instance-to-path ( buf-len buf-addr ihandle -- length ) Pathname of given instance package-to-path ( buf-len buf-addr phandle -- length ) Pathname of given package call-method ( ... ihandle method-cstr -- ... catch-result ) Call given method. open ( device-cstr -- ihandle ) Open given device specifier. close ( ihandle -- ) Close device instance. read ( len addr ihandle -- actual ) Execute read method. write ( len addr ihandle -- actual ) Execute write method. seek ( pos.lo pos.hi ihandle -- status ) Execute seek method. - Memory Group: claim ( align size virt -- baseaddr ) Generic memory allocation. release ( size virt -- ) Release memory resource. - Control Transfer Group: boot ( bootspec-cstr -- ) Reset and reboot system. enter ( -- ) Enter client interface. exit ( -- ) Exit to client interface. chain ( args-len args-addr entry size virt -- ) Chain to another client program - User Interface Group: interpret ( ... cmd-cstr -- ... catch-result ) Interpret command string. set-callback ( newfunc -- oldfunc ) Set client CALLBACK handler set-symbol-lookup ( value-to-sym sym-to-value -- ) Set symbol support callbacks. 1.1.2. Client Interface Handler. A client interface handler compliant with this specification shall be implemented as follows: The client interface handler pushes the arguments from the client program argument array (if any) onto the stack in the proper order (argN is pushed first; arg1 is pushed last and is the top-most stack item). The client interface handler attempts to find the given method (client interface service name) in the "/openprom/client-services" package, and if found, executes the given method in that package. If the method is found and returns, the client interface handler pops results (if any) off the stack, in the proper order, storing them in the proper place in the return cells in the argument array, if there are any return cells in the argument array (the top-most stack item is returned in Ret1, and the bottom-most stack item is returned in RetN, assuming enough space exists in the argument array, as described in the core specification.) The client interface handler restores the stack to its initial state (the state at the time the client interface handler was invoked) and restores device context to its initial state (the active package, if any, at the time the client interface handler was invoked, is restored) before returning to the client program. 1.2. Extending the client interface. Client programs and/or other packages may extend the client interface by adding new methods or by redefining methods in the "/openprom/client-services" package. A client program or package can use the FIND-PACKAGE, FIND-METHOD, PUSH-PACKAGE and POP-PACKAGE FCode functions (if the device interface is present) to extend the client interface. NOTE: Client programs and/or other packages that redefine existing methods should be careful to maintain semantics compliant with the core specification. 1.3. New and modified FCode Functions. The FIND-PACKAGE FCode function definition is modified in the following upwards compatible manner. Implementations compliant with this supplement and including the device interface shall implement the FIND-PACKAGE FCode function as described below: find-package ( name-string name-len -- false | phandle true ) F 0x204 Locate the support package named by *name-string*. If the package can be located, return its *phandle* and TRUE. Otherwise return FALSE. If the first character in *name-string* is '/', then interpret the name in *name-string* relative to the root of the device tree, otherwise, interpret the name in *name-string* relative to the "/packages" node. If there are multiple packages with the same name (within the "/packages" or parent node) return the *phandle* for the most recently created one. Implementations compliant with this supplement shall include the following FCode functions, if the client interface is present: push-package ( phandle -- ) F 0x129 Push active package and make phandle the active package. Make *phandle* the active package, saving the current active package handle (or an indication that there is no current active package) in such a way that POP-PACKAGE can undo the effect, in reverse order, of each execution of PUSH-PACKAGE. An implementation shall support a minimum of eight levels of execution of PUSH-PACKAGE without any intervening POP-PACKAGE. PUSH-PACKAGE and POP-PACKAGE are paired only relative to each other, and need not be balanced with respect to use of the Forth data and return stacks. NOTE: PUSH-PACKAGE and POP-PACKAGE are intended to be used as a "stacking" mechanism, as the names imply. pop-package ( -- ) F 0x12A Undo the effect of the most recent execution of PUSH-PACKAGE, relative to each execution of POP-PACKAGE, making the previous active package the current active package, or unselecting the active package, leaving none selected if there was no previous active package (as with DEVICE-END). Subsequent executions of POP-PACKAGE, make the prior active package the active package, or leave none selected, relative to each execution of PUSH-PACKAGE. If there is no *paired* execution of POP-PACKAGE, THROW an error. An implementation shall support a minimum of eight levels of execution of PUSH-PACKAGE without any intervening POP-PACKAGE. PUSH-PACKAGE and POP-PACKAGE are paired only relative to each other, and need not be balanced with respect to use of the Forth data and return stacks. NOTE: PUSH-PACKAGE and POP-PACKAGE are intended to be used as a "stacking" mechanism of the active package, as the names imply. 1.4. Client Interface Glossary. This section defines the methods in the client-services package as defined in the client interface chapter of the core specification. 1.4.1 Notation. The notation and format of the glossary entries is identical to the form given in the core specification, with the following additions: - Stack Comment Field cstr xyz-cstr Address of a null-terminated string. A null-terminated string is a string of non-zero bytes followed by a single zero byte, terminating the "string". len addr Length and address (2 associated stack items) for memory region. xyz-len xyz-addr Length and address (2 associated stack items) for memory region. xyzQ ... xyz1 Denotes one or more arbitrary xyzP ... xyz1 stack items that may or may not be present. - Type Codes Field K Denotes a client-services support package method. If supported, the given method exists in the "/openprom/client-services" package. 1.4.2. Glossary. boot ( bootspec-cstr -- ) K Reset and reboot system. Exit the client program, reset the system (as with RESET-ALL) and re-boot the system with the device and arguments given by the null-terminated string *bootspec-cstr*. The string *bootspec-cstr* is interpreted in the same manner as the arguments of the user interface command BOOT. See also: enter, exit call-method ( stack-argP ... stack-arg1 ihandle, method-cstr -- stack-resultQ ... stack-result1 catch-result ) K Call given method, guarded by catch. Client Services method: Executes the package method named *method-cstr* in the instance *ihandle* as with $CALL-METHOD, guarded by CATCH, returning the result of CATCH in *catch-result*. An implementation shall allow at least six *stack-arg* and six *stack-result* items. Note: The stack-arguments and stack-results may or may not be present, depending on the specific method being executed. Client Interface Handler: The client interface handler pushes *N_args - 2* items, *stack-arg1, ..., stack-argP*, onto the Forth data stack, with *stack-arg1* on top of the stack, then pushes *ihandle* and *method-cstr* onto the top of the stack and calls this method. If *catch-result* is zero, the client interface handler pops up to *N_returns - 1* items from the Forth data stack into the returned values portion of the argument array, with *stack-result1* corresponding to the top of the stack (after *catch-result* is popped from the stack). *N_args* and *N_returns* are stored in the argument array, and may be different for different calls to CALL-METHOD. If the number of items, *X*, left on the Forth data stack as a result of the execution of *method-cstr* is less than *N_returns*, only *stack-result1, ..., stack-resultX* are stored in the argument array and returned to the caller; other elements of the returned values portion of the argument array are unaffected. If *X* is more than *N_returns*, additional items are popped from the Forth data stack after storing *stack-result1, ..., stack-resultQ* in the argument array, so that, in all cases, the execution of CALL-METHOD results in no net change to the depth of the Forth data stack. See also: $call-method, catch canon ( buf-len buf-addr device-cstr -- length ) K Fully qualify a device specifier. Converts the possibly-ambiguous device specifier, *device-cstr*, to a fully-qualified pathname, storing at most *buf-len* bytes as a null-terminated string in the memory buffer whose address is given in *buf-addr*. If the actual length of the null- terminated pathname is greater than *buf-len*, the trailing characters and the null-terminator are not stored. Returns *length*, the actual length of the fully-qualified pathname excluding the null-terminator, or -1 if the pathname is invalid. NOTE: This service can be used to expand device aliases. See also: finddevice chain ( args-len args-addr entry size virt -- ) K Chain to another client program Frees *size* bytes of memory beginning at address *virt*, then executes a new client program beginning at address *entry*. The argument buffer *args-addr*, *args-len* is copied into the boot firmware's memory and passed to the new client program. The address of the arguments in the boot firmware's memory is the new client program's second argument, and their length is its third argument. CHAIN is used to free any remaining memory for a secondary boot program and begin executing the booted program. child ( phandle -- child-phandle ) K Device tree navigation; Get first child. Return, in *child-phandle*, the identifier of the device node that is the first child of the device node identified by *phandle*, or zero if there are no children. See also: peer, parent claim ( align size virt -- baseaddr ) K Generic memory allocation. Allocates *size* bytes of memory. If *align* is zero, the allocated range begins at the virtual address *virt*. Otherwise, an aligned address is automatically chosen and the stack argument *virt* is ignored. The alignment boundary is the smallest power of two greater than or equal to the value of *align*; an *align* value of 1 signifies one-byte alignment. *Baseaddr* is the beginning address of the allocated memory region (equal to *virt* is *align* is zero) or -1 if the operation fails (for example, if the requested virtual address is unavailable). The range of physical memory and virtual addresses affected by this operation will be unavailable for subsequent mapping or allocation operations, until freed by RELEASE. See also: release close ( ihandle -- ) K Close device instance. Closes the instance identified by *ihandle* as with CLOSE-DEV; subsequent use of that *ihandle* is invalid. Note: A client program should close instance it has opened after the instances are no longer needed, in order to release resources and to deactivate any associated devices. See also: close-dev, open, read, write, seek enter ( -- ) K Enter client interface. Enter the boot firmware command interpreter, if the user interface is present. The client program may be resumed if the user continues execution with the GO user interface command. Note: May be used by an operating system after a console input device abort sequence. See also: boot, exit exit ( -- ) K Exit to client interface. Exit the client program. The client program may not be resumed. See also: boot, enter finddevice ( device-cstr -- phandle ) K Return *phandle* of given device specifier. Returns *phandle*, the identifier of the device node selected by the device specifier, *device-cstr*, as with FIND-DEVICE, or -1 if *device-cstr* cannot be matched. The *active package* is unaffected. See also: canon, FIND-DEVICE getprop ( len addr name-cstr phandle -- size ) K Get property value. Copies a maximum of *len* bytes of the value of the property *name-cstr* in the device node identified by *phandle* into the memory pointed to be *addr*. Returns, in *size*, the actual size of the property (as with "getproplen") or -1 if the the property *name-cstr* does not exist. See also: getproplen getproplen ( name-cstr phandle -- prop-len ) K Get property length. Returns, in *prop-len*, the length of the value associated with the property *name-cstr* in the device node identified by *phandle*, zero if the property *name-cstr* exists but has no value, or -1 if the property *name-cstr* does not exist. instance-to-package ( ihandle -- phandle ) K Return package handle corresponding to given instance. Return, in *phandle*, the identifier of the package corresponding to the instance identifier *ihandle*. *Phandle* is -1 if there is no instance identifier *ihandle*. If *phandle* is -1, the boot firmware was unable to translate *ihandle*. The boot firmware *may*, but is not required to, check the validity of an *ihandle*. See also: instance-to-path instance-to-path ( buf-len buf-addr ihandle -- length ) K Return pathname of given instance. Returns the fully-qualified pathname corresponding to the identifier *ihandle*, storing at most *buf-len* bytes as a null-terminated string in the memory buffer starting at the address *buf-addr*. If the length of the null-terminated pathname is greater than *buf-len*, the trailing characters and the null-terminator are not stored. Returns *length*, the length, in bytes, of the fully-qualified pathname excluding the null-terminator, or -1 if *ihandle* is invalid. See also: instance-to-package interpret ( stack-argP ... stack-arg1 cmd-cstr -- stack-resultQ ... stack-result1 catch-result ) K Interpret command string. Client Services Method: Executes the null-terminated string *cmd-cstr* as a Forth command line, guarded by CATCH, returning the result of CATCH in *catch-result*. *Stack-argP, ..., stack-arg1*, if present, are left on top of the stack and may be used as arguments by the Forth command, *cmd-cstr*. An implementation shall allow at least six *stack-arg* and six *stack-result* items. Note: The stack-arguments and stack-results may or may not be present, depending on the specific Forth command. INTERPRET is optional; it need be present only if the Open Firmware User Interface is present. Client Interface Handler: The client interface handler pushes *N_args - 2* items, *stack-arg1, ..., stack-argP*, onto the Forth data stack, with *stack-arg1* on top of the stack, then pushes *cmd-cstr* onto the top of the stack and calls this method. If *catch-result* is zero, the client interface handler pops up to *N_returns - 1* items from the Forth data stack into the returned values portion of the argument array, with *stack-result1* corresponding to the top of the stack (after *catch-result* is popped from the stack). *N_args* and *N_returns* are stored in the argument array, and may be different for different calls to INTERPRET. If the number of items, *X*, left on the Forth data stack as a result of the execution of *method-cstr* is less than *N_returns*, only *stack-result1, ..., stack-resultX* are stored in the argument array and returned to the caller; other elements of the returned values portion of the argument array are unaffected. If *X* is more than *N_returns*, additional items are popped from the Forth data stack after storing *stack-result1, ..., stack-resultQ* in the argument array, so that, in all cases, the execution of INTERPRET results in no net change to the depth of the Forth data stack. See also: catch nextprop ( buf-addr prev-cstr phandle -- flag ) K Get next property name. Copies the name of the property following *prev-cstr* in the property list of the device node identified by *phandle* into *buf-addr*, as a NULL terminated string. *Buf-addr* is the address of a 32 byte buffer. If *prec-cstr* is zero or a pointer to a *null string* (the first byte of a *null string* is zero), copies the name of the device node's first property. If there are no more properties after *prev-cstr* or if *prev-cstr* is invalid (i.e., names a property which does not exist in that device node), copies a null string. The return value *flag* is -1 if *prev-cstr* is invalid, zero if there are no more properties after *prev-cstr*, or one (1) otherwise. open ( device-cstr -- ihandle ) K Open given device specifier. Open the package named by the device specifier *device-cstr* as with OPEN-DEV, returning the instance identifier *ihandle*. *Ihandle* is zero if the operation fails. The same package can be opened more than once if the particular package permits it, in which case a distinct *ihandle* will be returned each time. See also: open-dev, close, read, write, seek package-to-path ( buf-len buf-addr phandle -- length ) K Return pathname of given package. Returns the fully-qualified pathname corresponding to the identifier *phandle*, storing at most *buf-len* bytes as a null-terminated string in the memory buffer starting at the address *buf-addr*. If the length of the null-terminated pathname is greater than *buf-len*, the trailing characters and the null-terminator are not stored. Returns *length*, the length, in bytes, of the fully-qualified pathname excluding the null-terminator, or -1 if *phandle* is invalid. parent ( phandle -- parent-phandle ) K Device tree navigation; Get parent. Return, in *parent-phandle*, the identifier of the device node that is the parent of the device node identified by *phandle*, or zero if *phandle* is the root device node. See also: child, peer peer ( phandle -- sibling-phandle ) K Device tree navigation; Get next sibling. Returns, in *sibling-phandle*, the identifier of the device node that is the next sibling of the device node identified by *phandle*, or zero of there are no more siblings. If *phandle* is zero, *sibling-phandle* is the identifier of the root device node. See also: child, parent read ( len addr ihandle -- actual ) K Execute read method. Execute the READ method in the instance *ihandle* with arguments *addr* and *len*. *Actual* is the value returned by that READ method or -1 if that instance does not have a READ method. See also: open, close, seek, write release ( size virt -- ) K Release memory resources. Frees *size* bytes of physical memory starting at virtual address *virt*, making that physical memory and the corresponding range of virtual address space available for later use. That memory must have been previously allocated using the CLAIM client service. See also: claim seek ( pos.lo pos.hi ihandle -- status ) K Execute seek method. Execute the SEEK method in the instance *ihandle* with the arguments *pos.hi* and *pos.lo*. *Status* is the value returned by that SEEK method, or -1 if that instance does not have a SEEK method. See also: open, close, read, write set-callback ( newfunc -- oldfunc ) K Set client CALLBACK handler Client programs may define a callback handler for handling the boot firmware's CALLBACK and SYNC user interface commands. Client Services Method: Sets the callback handler (for the CALLBACK and $CALLBACK user interface commands) to *newfunc* and returns the address of the entry point of the previously installed callback handler as *oldfunc*. Callback Semantics: The boot firmware shall use the same calling conventions specified in the client interface section of the core specification for client services when calling the callback handler. See CALLBACK and $CALLBACK user interface glossary entries (in the core specification) for details. Client Program Callback Handler Semantics: A client program callback handler shall return a non-zero error code in the *ret1* cell of the argument array if the service indicated by the service argument is unavailable, or zero otherwise. The client program callback handler shall return any additional results in the *ret2, ..., retN* cells, setting *N_returns* to the total number of return values including the error code (or zero) that is in the *ret1* cell. The handler shall not store more than *M* results, where *M* is the value that was in the *N_returns* cell when the handler was called, nor shall the returned value of *N_returns* exceed *M*. See also: callback, $callback, sync setprop ( len addr name-cstr phandle -- size ) K Set property value. Sets the property value of the property *name-cstr* in the device node identified by *phandle* to the value beginning at memory address *addr* and continuing for *len* bytes, attempting to create the property if it does not exist. Returns, *size*, the actual length of the new value, or -1 if the property value could not be set or could not be created. set-symbol-lookup ( value-to-sym sym-to-value -- ) K Set symbol support callbacks. Client Services Method: Set the symbol table resolution defer words SYM>VALUE and VALUE>SYM so that they execute the client program callbacks whose addresses are given by the stack arguments *sym-to-value* and *value-to-sym*, respectively. If either argument is zero, the corresponding defer word is set the action of FALSE. set-symbol-lookup is optional; it need be present only if the boot firmware's user interface is present and the Symbolic Debugging Command Group is implemented. Client Program Callback Handler Semantics: *Sym-to-value* is called as follows: IN: [string] symname-cstr OUT: error, symvalue *Sym-to-value* searches for a symbol whose name is *symname-cstr*. If such a symbol is found, return zero in *error* and the symbol's value in *symvalue*. If no such symbol is found, returns -1 in *error* and zero in *symvalue*. *Value-to-sym* is called as follows: IN: symvalue OUT: offset, [string] symname-cstr Locate the symbol whose value is closest to but not greater than *symvalue*, returning *offset*, the non-negative offset from the value of that symbol to *symvalue*, and *symname-cstr*, the symbol name. If *symvalue* is less than the value of any known symbol, or is insufficiently close to any symbol value according to an implementation-dependent criterion, returns -1 in *offset* and a pointer to a null string in *symname-cstr*. test ( method-cstr -- missing? ) K Test for existence of method. Returns, in *missing?*, 0 if the client service *method-cstr* exists, and -1 if it does not exist. write ( len addr ihandle -- actual ) K Execute write method. Execute the WRITE method in the instance *ihandle* with the arguments *addr* and *len*. *Actual* is the value returned by that WRITE method, or -1 if that instance does not have a WRITE method. See also: open, close, seek, read [ P1275 Item #215 -- Received: Tue Dec 6 18:04:45 PST 1994 ]