diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 000000000..f870fed90
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,45 @@
+---
+name: Bug report
+about: Create a report to help us improve.
+title: ''
+labels: bug, new
+---
+
+
+
+**Describe the bug**
+
+**Steps to Reproduce**
+
+1.
+2.
+
+**Expected behavior**
+
+**Screenshots (if needed)**
+
+**Logs**
+
+
+
+
+
+
+
+
+
+
+**Describe your environment**
+
+
+- Zowe version number (Check the Desktop login screen, or manifest.json in the Zowe install folder):
+- Install method (pax, smpe, kubernetes, github clone):
+- Operating system (z/OS, kubernetes, etc) and OS version:
+- Node.js version number (Shown in logs, or via `node --version`):
+- Java version number (Shown in logs, or via `java -version`):
+- z/OSMF version:
+- What is the output of log message ZWES1014I:
+- Environment variables in use:
+
+
+**Additional context**
diff --git a/.github/ISSUE_TEMPLATE/bug_report_high.md b/.github/ISSUE_TEMPLATE/bug_report_high.md
new file mode 100644
index 000000000..2a055864e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report_high.md
@@ -0,0 +1,45 @@
+---
+name: High-severity bug report
+about: Create a report on a high-severity bug. High severity is when there is an issue that has a major impact on usage of Zowe.
+title: ''
+labels: bug, new, severity-high
+---
+
+
+
+**Describe the bug**
+
+**Steps to Reproduce**
+
+1.
+2.
+
+**Expected behavior**
+
+**Screenshots (if needed)**
+
+**Logs**
+
+
+
+
+
+
+
+
+
+
+**Describe your environment**
+
+
+- Zowe version number (Check the Desktop login screen, or manifest.json in the Zowe install folder):
+- Install method (pax, smpe, kubernetes, github clone):
+- Operating system (z/OS, kubernetes, etc) and OS version:
+- Node.js version number (Shown in logs, or via `node --version`):
+- Java version number (Shown in logs, or via `java -version`):
+- z/OSMF version:
+- What is the output of log message ZWES1014I:
+- Environment variables in use:
+
+
+**Additional context**
diff --git a/.github/ISSUE_TEMPLATE/bug_report_low.md b/.github/ISSUE_TEMPLATE/bug_report_low.md
new file mode 100644
index 000000000..e47807673
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report_low.md
@@ -0,0 +1,45 @@
+---
+name: Low-severity bug report
+about: Create a report on a low-severity bug. Low severity is when there is an issue that is inconvenient but doesn't impact key use cases.
+title: ''
+labels: bug, new, severity-low
+---
+
+
+
+**Describe the bug**
+
+**Steps to Reproduce**
+
+1.
+2.
+
+**Expected behavior**
+
+**Screenshots (if needed)**
+
+**Logs**
+
+
+
+
+
+
+
+
+
+
+**Describe your environment**
+
+
+- Zowe version number (Check the Desktop login screen, or manifest.json in the Zowe install folder):
+- Install method (pax, smpe, kubernetes, github clone):
+- Operating system (z/OS, kubernetes, etc) and OS version:
+- Node.js version number (Shown in logs, or via `node --version`):
+- Java version number (Shown in logs, or via `java -version`):
+- z/OSMF version:
+- What is the output of log message ZWES1014I:
+- Environment variables in use:
+
+
+**Additional context**
diff --git a/.github/ISSUE_TEMPLATE/bug_report_medium.md b/.github/ISSUE_TEMPLATE/bug_report_medium.md
new file mode 100644
index 000000000..86e45dc95
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report_medium.md
@@ -0,0 +1,45 @@
+---
+name: Medium-severity bug report
+about: Create a report on a medium-severity bug. Medium severity is when there is an issue that makes the use of Zowe difficult, but has a workaround or doesn't prevent the use of Zowe.
+title: ''
+labels: bug, new, severity-medium
+---
+
+
+
+**Describe the bug**
+
+**Steps to Reproduce**
+
+1.
+2.
+
+**Expected behavior**
+
+**Screenshots (if needed)**
+
+**Logs**
+
+
+
+
+
+
+
+
+
+
+**Describe your environment**
+
+
+- Zowe version number (Check the Desktop login screen, or manifest.json in the Zowe install folder):
+- Install method (pax, smpe, kubernetes, github clone):
+- Operating system (z/OS, kubernetes, etc) and OS version:
+- Node.js version number (Shown in logs, or via `node --version`):
+- Java version number (Shown in logs, or via `java -version`):
+- z/OSMF version:
+- What is the output of log message ZWES1014I:
+- Environment variables in use:
+
+
+**Additional context**
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 000000000..842a135fa
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,25 @@
+---
+name: Feature request
+about: Suggest an idea for ZSS
+labels: enhancement, new
+---
+
+
+
+**Is your feature or enhancement request related to a problem or limitation? Please describe**
+
+
+
+**Describe your enhancement idea**
+
+
+
+
+**Describe alternatives you've considered**
+
+
+
+**Provide any additional context**
+
+
+
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 5cac6ad55..031980ccc 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -3,7 +3,7 @@
## Proposed changes
-This PR addresses Issue: [*Link to Github issue within https://github.com/zowe/zlux/issues* if any]
+This PR addresses Issue: [*Link to Github issue within https://github.com/zowe/zss/issues* if any]
This PR depends upon the following PRs:
@@ -19,7 +19,7 @@ Please delete options that are not relevant.
## PR Checklist
Please delete options that are not relevant.
- [ ] If the changes in this PR are meant for the next release / mainline, this PR targets the "staging" branch.
-- [ ] My code follows the style guidelines of this project (see: [Contributing guideline](https://github.com/zowe/zlux/blob/master/CONTRIBUTING.md))
+- [ ] My code follows the style guidelines of this project (see: [Contributing guideline](https://github.com/zowe/zss/blob/v2.x/master/CONTRIBUTING.md))
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] New and existing unit tests pass locally with my changes
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
new file mode 100644
index 000000000..bb9de01ab
--- /dev/null
+++ b/.github/workflows/stale.yml
@@ -0,0 +1,30 @@
+name: 'Close stale issues and PRs'
+on:
+ schedule:
+ - cron: '0 */6 * * *'
+
+permissions:
+ issues: write
+ pull-requests: write
+
+jobs:
+ stale:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/stale@v5
+ with:
+ close-issue-message: >
+ This issue has been automatically closed due to lack of activity.
+ If this issue is still valid and important to you, it can be reopened.
+ days-before-close: 90
+ days-before-stale: 180
+ exempt-all-assignees: true
+ exempt-all-milestones: true
+ exempt-issue-labels: "community-upvoted, dependency, for-review, keep, security, high-severity, critical-severity, help-wanted, good-first-issue"
+ stale-issue-label: "stale-reopen-if-needed"
+ stale-issue-message: >
+ This issue has been automatically marked as stale because it has not had
+ recent activity. It will be closed if no further activity occurs,
+ but can be reopened if needed. Thank you for your contributions.
+ stale-pr-label: "stale-reopen-if-needed"
+ start-date: "2022-05-30T00:00:00Z"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fa08c220f..2ca6c819b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,13 @@ All notable changes to the ZSS package will be documented in this file.
## Recent Changes
+## `2.5.0`
+
+- Bugfix: In 2.3 and 2.4, 'safkeyring://' syntax stopped working, only allowing 'safkeyring:////'. Now, support for both is restored.
+- Support ZIS runtime version check
+- Update the dynamic linkage stub vector to include new functions
+- Add ZIS plugin development documentation and samples
+
## `2.4.0`
- Enhancement: ZSS /datasetContents now has a PUT API for creating datasets.
diff --git a/c/zis/server-api.c b/c/zis/server-api.c
index 3b4fe0745..a8d59223f 100644
--- a/c/zis/server-api.c
+++ b/c/zis/server-api.c
@@ -32,9 +32,34 @@ _Bool zisIsLPADevModeOn(const ZISContext *context) {
}
void zisGetServerVersion(int *major, int *minor, int *revision) {
- *major = ZIS_MAJOR_VERSION;
- *minor = ZIS_MINOR_VERSION;
- *revision = ZIS_REVISION;
+ *major = -1;
+ *minor = -1;
+ *revision = -1;
+ CAA *caa = (CAA *)getCAA();
+ if (caa == NULL) {
+ return;
+ }
+ RLETask *task = caa->rleTask;
+ if (task == NULL) {
+ return;
+ }
+ RLEAnchor *rleAnchor = task->anchor;
+ if (rleAnchor == NULL) {
+ return;
+ }
+ ZISContext *context = NULL;
+ if (getRLEApplicationAnchor(rleAnchor, (void **)&context)) {
+ return;
+ }
+ if (!(context->zisAnchor->flags & ZIS_SERVER_ANCHOR_VERSIONED_CONTEXT)) {
+ return;
+ }
+ if (context->version < ZIS_CONTEXT_VERSION_ZIS_VERSION_SUPPORT) {
+ return;
+ }
+ *major = context->zisVersion.major;
+ *minor = context->zisVersion.minor;
+ *revision = context->zisVersion.revision;
}
/*
diff --git a/c/zis/server.c b/c/zis/server.c
index 51a1f100a..31744d26e 100644
--- a/c/zis/server.c
+++ b/c/zis/server.c
@@ -1109,6 +1109,7 @@ ZISServerAnchor *createZISServerAnchor() {
/* new feature bit for dynamic linking - Fall 2021 */
anchor->flags |= ZIS_SERVER_ANCHOR_FLAG_DYNLINK;
+ anchor->flags |= ZIS_SERVER_ANCHOR_VERSIONED_CONTEXT;
return anchor;
}
@@ -1118,6 +1119,10 @@ static void enableDynLink(ZISServerAnchor *anchor) {
anchor->flags |= ZIS_SERVER_ANCHOR_FLAG_DYNLINK;
}
+static void enableVersionedContext(ZISServerAnchor *anchor) {
+ anchor->flags |= ZIS_SERVER_ANCHOR_VERSIONED_CONTEXT;
+}
+
static void removeZISServerAnchor(ZISServerAnchor **anchor) {
unsigned int size = sizeof(ZISServerAnchor);
@@ -1143,6 +1148,8 @@ static int initGlobalResources(ZISContext *context) {
} else {
// make sure any existing anchors supports dynamic linkage now
enableDynLink(anchor);
+ // make sure it also supports a versioned ZIS context
+ enableVersionedContext(anchor);
}
context->zisAnchor = anchor;
@@ -1158,6 +1165,11 @@ static ZISContext makeContext(STCBase *base) {
ZISContext cntx = {
.eyecatcher = ZIS_CONTEXT_EYECATCHER,
+ .version = ZIS_CONTEXT_VERSION,
+ .size = sizeof(ZISContext),
+ .zisVersion.major = ZIS_MAJOR_VERSION,
+ .zisVersion.minor = ZIS_MINOR_VERSION,
+ .zisVersion.revision = ZIS_REVISION,
.stcBase = base,
.parms = NULL,
.cmServer = NULL,
@@ -1370,6 +1382,8 @@ static int initContext(ZISContext *context) {
memcpy(context->dynlinkModuleNameNullTerm, context->zisModuleName.text, 4);
strcat(context->dynlinkModuleNameNullTerm, ZIS_DYN_LINKAGE_PLUGIN_MOD_SUFFIX);
+ setRLEApplicationAnchor(context->stcBase->rleAnchor, context);
+
return RC_ZIS_OK;
}
diff --git a/c/zis/stubinit.c b/c/zis/stubinit.c
index 0d0327d07..63a2eca3b 100644
--- a/c/zis/stubinit.c
+++ b/c/zis/stubinit.c
@@ -273,6 +273,8 @@
stubVector[ZIS_STUB_LETMRLEE] = (void*)termRLEEnvironment;
stubVector[ZIS_STUB_LEMKFCAA] = (void*)makeFakeCAA;
stubVector[ZIS_STUB_LEARTCAA] = (void*)abortIfUnsupportedCAA;
+ stubVector[ZIS_STUB_LESETANC] = (void*)setRLEApplicationAnchor;
+ stubVector[ZIS_STUB_LEGETANC] = (void*)getRLEApplicationAnchor;
stubVector[ZIS_STUB_MKLOGCTX] = (void*)makeLoggingContext;
stubVector[ZIS_STUB_MKLLGCTX] = (void*)makeLocalLoggingContext;
stubVector[ZIS_STUB_RMLOGCTX] = (void*)removeLoggingContext;
diff --git a/c/zis/zisdynamic.c b/c/zis/zisdynamic.c
index 95195bede..da78dec56 100644
--- a/c/zis/zisdynamic.c
+++ b/c/zis/zisdynamic.c
@@ -90,6 +90,10 @@
ZOWE_PRAGMA_PACK
+#define ZIS_MIN_MAJOR_VERSION ZIS_MAJOR_VERSION
+#define ZIS_MIN_MINOR_VERSION ZIS_MINOR_VERSION
+#define ZIS_MIN_REVISION ZIS_REVISION
+
typedef struct ZISDynStubVector_tag {
#define ZISDYN_STUB_VEC_EYECATCHER "ZWESISSV"
@@ -386,8 +390,44 @@ void zisdynGetPluginVersion(int *major, int *minor, int *revision) {
*revision = ZISDYN_REVISION;
}
+static int verifyZISVersion(void) {
+
+ int zisMajor = 0;
+ int zisMinor = 0;
+ int zisRev = 0;
+ zisGetServerVersion(&zisMajor, &zisMinor, &zisRev);
+ zowelog(NULL, LOG_COMP_ID_CMS, ZOWE_LOG_DEBUG,
+ "ZIS major=%d, minor=%d, rev=%d\n", zisMajor, zisMinor, zisRev);
+
+ if (zisMajor != ZISDYN_MAJOR_VERSION) {
+ goto out_bad_version;
+ }
+ if (zisMinor < ZISDYN_MINOR_VERSION) {
+ goto out_bad_version;
+ }
+ if (zisMinor == ZISDYN_MINOR_VERSION && zisRev < ZISDYN_REVISION) {
+ goto out_bad_version;
+ }
+
+ return 0;
+
+ out_bad_version:
+ zowelog(NULL, LOG_COMP_ID_CMS, ZOWE_LOG_SEVERE,
+ ZISDYN_LOG_BAD_ZIS_VERSION_MSG,
+ ZIS_MIN_MAJOR_VERSION,
+ ZIS_MIN_MINOR_VERSION,
+ ZIS_MIN_REVISION,
+ ZIS_MIN_MAJOR_VERSION + 1,
+ zisMajor, zisMinor, zisRev);
+ return -1;
+}
+
ZISPlugin *getPluginDescriptor(void) {
+ if (verifyZISVersion() != 0) {
+ return NULL;
+ }
+
ZISPluginName pluginName = {.text = ZISDYN_PLUGIN_NAME};
ZISPluginNickname pluginNickname = {.text = ZISDYN_PLUGIN_NICKNAME};
diff --git a/defaults.yaml b/defaults.yaml
index 8d51ca126..c3d872d34 100644
--- a/defaults.yaml
+++ b/defaults.yaml
@@ -14,7 +14,7 @@ components:
fallback: true
retryIntervalSeconds: 10
https:
- keyring: ${{ ()=> { if (components.zss.tls) { if (zowe.certificate.keystore.type == "JCERACFKS") { return zowe.certificate.keystore.file.substring(15) } else { return zowe.certificate.keystore.file } } else { return null } }() }}
+ keyring: ${{ ()=> { if (components.zss.tls) { if (zowe.certificate.keystore.type == "JCERACFKS") { return zowe.certificate.keystore.file.replace(/safkeyring:\/+/,"") } else { return zowe.certificate.keystore.file } } else { return null } }() }}
password: ${{ ()=> { if (components.zss.tls) { if (zowe.certificate.keystore.type == "JCERACFKS") { return null } else { return zowe.certificate.keystore.password } } else { return null } }() }}
label: ${{ ()=> { if (components.zss.tls) { return zowe.certificate.keystore.alias } else { return null } }() }}
port: ${{ ()=> { if (components.zss.tls) { return components.zss.port } else { return null } }() }}
diff --git a/deps/zowe-common-c b/deps/zowe-common-c
index f1bcf35a3..4f2732d0e 160000
--- a/deps/zowe-common-c
+++ b/deps/zowe-common-c
@@ -1 +1 @@
-Subproject commit f1bcf35a37772e4d17886547393955dbf414ed3c
+Subproject commit 4f2732d0e781aec89b39f862262d5014a97c09b7
diff --git a/h/zis/message.h b/h/zis/message.h
index fead6486b..202350676 100644
--- a/h/zis/message.h
+++ b/h/zis/message.h
@@ -272,7 +272,7 @@
#define ZISDYN_LOG_TERM_MSG_TEXT "ZIS Dynamic Base plugin terminating"
#define ZISDYN_LOG_TERM_MSG ZISDYN_LOG_TERM_MSG_ID" "ZISDYN_LOG_TERM_MSG_TEXT
-#define ZISDYN_LOG_TERMED_MSG_ID ZIS_MSG_PRFX"02045"
+#define ZISDYN_LOG_TERMED_MSG_ID ZIS_MSG_PRFX"0205I"
#define ZISDYN_LOG_TERMED_MSG_TEXT "ZIS Dynamic Base plugin successfully terminated"
#define ZISDYN_LOG_TERMED_MSG ZISDYN_LOG_TERMED_MSG_ID" "ZISDYN_LOG_TERMED_MSG_TEXT
@@ -304,6 +304,10 @@
#define ZISDYN_LOG_DEV_MODE_MSG_TEXT "ZIS Dynamic base plugin development mode is enabled"
#define ZISDYN_LOG_DEV_MODE_MSG ZISDYN_LOG_DEV_MODE_MSG_ID" "ZISDYN_LOG_DEV_MODE_MSG_TEXT
+#define ZISDYN_LOG_BAD_ZIS_VERSION_MSG_ID ZIS_MSG_PRFX"0214E"
+#define ZISDYN_LOG_BAD_ZIS_VERSION_MSG_TEXT "Bad cross-memory server version: expected [%d.%d.%d, %d.0.0), found %d.%d.%d"
+#define ZISDYN_LOG_BAD_ZIS_VERSION_MSG ZISDYN_LOG_BAD_ZIS_VERSION_MSG_ID" "ZISDYN_LOG_BAD_ZIS_VERSION_MSG_TEXT
+
#endif /* ZIS_MSG_H_ */
diff --git a/h/zis/plugin.h b/h/zis/plugin.h
index 76cb341ea..fd192e5ab 100644
--- a/h/zis/plugin.h
+++ b/h/zis/plugin.h
@@ -86,7 +86,8 @@ struct ZISPlugin_tag {
#define ZIS_PLUGIN_VERSION 1
unsigned int size;
int flags;
-#define ZIS_PLUGIN_FLAG_LPA 0x00000001
+#define ZIS_PLUGIN_FLAG_NONE 0x00000000
+#define ZIS_PLUGIN_FLAG_LPA 0x00000001
unsigned int maxServiceCount;
/* These are used by the server */
@@ -120,6 +121,21 @@ typedef ZISPlugin *(ZISPluginDescriptorFunction)();
#pragma map(zisCreatePluginAnchor, "ZISPLGCA")
#pragma map(zisRemovePluginAnchor, "ZISPLGRM")
+/**
+ * @brief Create a plugin descriptor.
+ * @param[in] name The plugin name (unique within ZIS).
+ * @param[in] nickname The plugin nickname unique within ZIS.
+ * @param[in] initFunction The init callback function invoked at ZIS startup.
+ * @param[in] termFunction The term callback function invoked at ZIS termination.
+ * @param[in] commandFunction The command handler function invoked when a user
+ * issues a modify command using the plugin's nickname as target.
+ * @param[in] version The plugin version (when bumped forces ZIS to load the new
+ * version of the plugin module to LPA if it's an LPA plugin).
+ * @param[in] serviceCount The number of services in this plugin.
+ * @param[in] flags Various flags (use the @c ZIS_PLUGIN_FLAG_xxxx values).
+ * @return The descriptor address if success, @c NULL in case of an allocation
+ * error.
+ */
ZISPlugin *zisCreatePlugin(ZISPluginName name,
ZISPluginNickname nickname,
ZISPuginInitFunction *initFunction,
@@ -129,8 +145,22 @@ ZISPlugin *zisCreatePlugin(ZISPluginName name,
unsigned int serviceCount,
int flags);
+/**
+ * @brief Remove the plugin descriptor (releases its memory).
+ * @param[in,out] plugin The plugin descriptor to be removed.
+ */
void zisDestroyPlugin(ZISPlugin *plugin);
+/**
+ * @brief Add a service to a plugin.
+ * @param[in,out] plugin The plugin descriptor to be used.
+ * @param[in] service The service to be added.
+ * @return
+ * - @c RC_ZIS_PLUGIN_OK in case of success
+ * - @c RC_ZIS_PLUGIN_INCOMPATIBLE_SEVICE if a PC-cp service is used with
+ * a non-LPA plugin
+ * - @c RC_ZIS_PLUGIN_BAD_SERVICE_NAME if the service name is invalid
+ */
int zisPluginAddService(ZISPlugin *plugin, ZISService service);
ZISPluginAnchor *zisCreatePluginAnchor();
diff --git a/h/zis/server-api.h b/h/zis/server-api.h
index 70db7d160..d0fb07496 100644
--- a/h/zis/server-api.h
+++ b/h/zis/server-api.h
@@ -20,7 +20,7 @@
#pragma map(zisIsLPADevModeOn, "ZISLPADV")
/**
- * Get the version of ZIS.
+ * Get the version of ZIS. In case of failure, all the results are set to -1.
* @param[out] major The major ZIS version.
* @param[out] minor The minor ZIS version.
* @param[out] revision The revision of ZIS (aka the patch version).
diff --git a/h/zis/server.h b/h/zis/server.h
index b49cd45da..84aa4e45e 100644
--- a/h/zis/server.h
+++ b/h/zis/server.h
@@ -33,9 +33,23 @@ typedef struct ZISContext_tag {
int cmsFlags;
EightCharString zisModuleName;
char dynlinkModuleNameNullTerm[9];
+ char reserved0[3];
+
+ int16_t version;
+#define ZIS_CONTEXT_VERSION 2
+#define ZIS_CONTEXT_VERSION_ZIS_VERSION_SUPPORT 2
+ uint16_t size;
+ uint32_t flags;
+ struct {
+ int32_t major;
+ int32_t minor;
+ int32_t revision;
+ } zisVersion;
+
} ZISContext;
#define ZIS_SERVER_ANCHOR_FLAG_DYNLINK 0x0001 /* supports dynamic linkage */
+#define ZIS_SERVER_ANCHOR_VERSIONED_CONTEXT 0x0002
typedef struct ZISServerAnchor_tag {
char eyecatcher[8];
diff --git a/h/zis/service.h b/h/zis/service.h
index a0651adfc..aa97efd31 100644
--- a/h/zis/service.h
+++ b/h/zis/service.h
@@ -123,12 +123,33 @@ ZOWE_PRAGMA_PACK_RESET
#pragma map(zisUpdateServiceAnchor, "ZISUSVCA")
#pragma map(zisServiceUseSpecificAuth, "ZISUSAUT")
+/**
+ * @brief Create a service descriptor.
+ * @param[in] name The service name (unique within the plugin).
+ * @param[in] flags Various flags (use the @c ZIS_SERVICE_FLAG_xxxx values).
+ * @param[in] initFunction The init callback function invoked at ZIS startup.
+ * @param[in] termFunction The term callback function invoked at ZIS termination.
+ * @param[in] serveFunction The serve callback function invoked when the service
+ * is called.
+ * @param[in] version The version of the service.
+ * @return The result service descriptor.
+ */
ZISService zisCreateService(ZISServiceName name, int flags,
ZISServiceInitFunction *initFunction,
ZISServiceTermFunction *termFunction,
ZISServiceServeFunction *serveFunction,
unsigned int version);
+/**
+ * @brief Create service descriptor for a space-switch service.
+ * @param[in] name The service name (unique within the plugin).
+ * @param[in] initFunction The init callback function invoked at ZIS startup.
+ * @param[in] termFunction The term callback function invoked at ZIS termination.
+ * @param[in] serveFunction The serve callback function invoked when the service
+ * is called.
+ * @param[in] version The version of the service.
+ * @return The result service descriptor.
+ */
ZISService zisCreateSpaceSwitchService(
ZISServiceName name,
ZISServiceInitFunction *initFunction,
@@ -137,6 +158,16 @@ ZISService zisCreateSpaceSwitchService(
unsigned int version
);
+/**
+ * @brief Create service descriptor for a current-primary service.
+ * @param[in] name The service name (unique within the plugin).
+ * @param[in] initFunction The init callback function invoked at ZIS startup.
+ * @param[in] termFunction The term callback function invoked at ZIS termination.
+ * @param[in] serveFunction The serve callback function invoked when the service
+ * is called.
+ * @param[in] version The version of the service.
+ * @return The result service descriptor.
+ */
ZISService zisCreateCurrentPrimaryService(
ZISServiceName name,
ZISServiceInitFunction *initFunction,
@@ -148,9 +179,9 @@ ZISService zisCreateCurrentPrimaryService(
/**
* Adds class and entity names to a service.
*
- * @param service The service to be used with the class and entity.
- * @param className The class name to be used.
- * @param entityName The entity name to be used.
+ * @param[in,out] service The service to be used with the class and entity.
+ * @param[in] className The class name to be used.
+ * @param[in] entityName The entity name to be used.
* @return 0 in case of success, -1 if the class or entity name is too long.
*/
int zisServiceUseSpecificAuth(ZISService *service,
diff --git a/h/zis/zisstubs.h b/h/zis/zisstubs.h
index 06ad5201a..13a0a66e2 100644
--- a/h/zis/zisstubs.h
+++ b/h/zis/zisstubs.h
@@ -20,7 +20,7 @@
FULL BACKWARD COMPATIBILITY MUST BE MAINTAINED
*/
-#define ZIS_STUBS_VERSION 2
+#define ZIS_STUBS_VERSION 3
/*
How does a user check for compatibility?
@@ -362,6 +362,8 @@
#define ZIS_STUB_LETMRLEE 457 /* termRLEEnvironment */
#define ZIS_STUB_LEMKFCAA 458 /* makeFakeCAA */
#define ZIS_STUB_LEARTCAA 459 /* abortIfUnsupportedCAA */
+#define ZIS_STUB_LESETANC 460 /* setRLEApplicationAnchor */
+#define ZIS_STUB_LEGETANC 461 /* getRLEApplicationAnchor */
/* logging, 470-499 */
#define ZIS_STUB_MKLOGCTX 470 /* makeLoggingContext */
diff --git a/plugins/zis/README.md b/plugins/zis/README.md
new file mode 100644
index 000000000..f00153be4
--- /dev/null
+++ b/plugins/zis/README.md
@@ -0,0 +1,592 @@
+This program and the accompanying materials are
+made available under the terms of the Eclipse Public License v2.0 which accompanies
+this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html
+
+SPDX-License-Identifier: EPL-2.0
+
+Copyright Contributors to the Zowe Project.
+___
+
+# ZIS plugin development
+
+
+* [ZIS plugin development](#zis-plugin-development)
+ * [Preface](#preface)
+ * [Terminology](#terminology)
+ * [Overview](#overview)
+ * [What is Zowe Cross-Memory Server?](#what-is-zowe-cross-memory-server)
+ * [When do I need ZIS?](#when-do-i-need-zis)
+ * [Extending ZIS](#extending-zis)
+ * [Plugin structure](#plugin-structure)
+ * [Module](#module)
+ * [Services](#services)
+ * [Callbacks](#callbacks)
+ * [Plugin lifecycle](#plugin-lifecycle)
+ * [ZIS startup](#zis-startup)
+ * [ZIS termination](#zis-termination)
+ * [Service call](#service-call)
+ * [z/OS operator modify command invocation](#zos-operator-modify-command-invocation)
+ * [Making a plugin](#making-a-plugin)
+ * [Plugin descriptor](#plugin-descriptor)
+ * [Plugin name](#plugin-name)
+ * [Plugin nickname](#plugin-nickname)
+ * [Plugin flags](#plugin-flags)
+ * [Plugin version](#plugin-version)
+ * [Plugin services](#plugin-services)
+ * [Service name](#service-name)
+ * [Service flags](#service-flags)
+ * [Service serve function](#service-serve-function)
+ * [Putting it all together](#putting-it-all-together)
+ * [Building a plugin](#building-a-plugin)
+ * [Compilation](#compilation)
+ * [Compiler requirements](#compiler-requirements)
+ * [Assembly](#assembly)
+ * [Assembler requirements](#assembler-requirements)
+ * [Recommended options](#recommended-options)
+ * [Linking](#linking)
+ * [Linker requirement](#linker-requirement)
+ * [Dynamic linkage stub](#dynamic-linkage-stub)
+ * [Deploying a plugin](#deploying-a-plugin)
+ * [Dynamic linkage considerations](#dynamic-linkage-considerations)
+ * [Plugin details](#plugin-details)
+ * [Serve function environment](#serve-function-environment)
+ * [Other callbacks' environment](#other-callbacks-environment)
+ * [User parameter list](#user-parameter-list)
+ * [Accessing caller's data](#accessing-callers-data)
+ * [Function return codes](#function-return-codes)
+ * [PC-ss vs PC-cp service](#pc-ss-vs-pc-cp-service)
+ * [Notes](#notes)
+ * [Plugin security](#plugin-security)
+ * [Dev mode](#dev-mode)
+ * [General ZIS dev mode](#general-zis-dev-mode)
+ * [LPA dev mode](#lpa-dev-mode)
+
+
+## Preface
+
+**IMPORTANT:** Zowe Cross-Memory Server plugins execute with elevated
+privileges, writing code for plugins requires you to be familiar with the
+operating system, principles of cross memory communication and implications of
+running your code in an authorized environment.
+
+Before making a new plugin, we recommend that extenders read the following
+sources:
+* [Synchronous cross memory communication](https://www.ibm.com/docs/en/zos/2.5.0?topic=guide-synchronous-cross-memory-communication)
+
+## Terminology
+
+Before we start, we need to clarify some abbreviations and terminology.
+* A/S - address space
+* HASN/PASN/SASN - the home/primary/secondary address space
+* HLASM - High Level Assembler
+* LPA - the link pack area
+* PC - program call
+ * PC-ss - space-switch PC
+ * PC-cp - current-primary PC
+* ZIS - Zowe Cross-Memory Server
+
+## Overview
+
+### What is Zowe Cross-Memory Server?
+* Zowe Cross-Memory Server (also known as ZIS) is an authorized server
+application that provides both privileged services and cross-memory services to unprivileged
+applications on z/OS in a secure manner.
+* Each ZIS instance is identified by a unique 16-character name (LPAR wide)
+* ZIS runs as a started task
+
+### When do I need ZIS?
+* Your service code requires a system key, supervisor state and/or
+APF-authorization
+* You want to provide services to applications that can’t use HTTP or the
+standard IPC mechanisms
+
+### Extending ZIS
+ZIS has the ability to be extended with third-party plugins. Usually, a plugin
+consists of a single load module and a line of configuration. This document
+will specifically go into details on how to develop and use ZIS plugins.
+
+Throughout this document we'll use snippets from the sample plugin code in [zss/plugins/zis/sample/](https://github.com/zowe/zss/tree/82c6f2d30951d64fb1bb6487c2dde92700b91552/plugins/zis/sample).
+Refer to that source for the full plugin sample.
+
+## Plugin structure
+
+### Module
+A ZIS plugin is a load module with the following characteristics:
+* AMODE 64
+* Reentrant
+* The result of call a ZIS plugin lod module is a plugin descriptor data
+structure mapped by the C struct [`ZISPlugin`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/plugin.h#L81-L112)
+
+### Services
+Each plugin consists of 0 or more services which are invoked via the PC
+instruction (program call).
+
+### Callbacks
+
+There are several callbacks plugin developers can set to better control
+the lifecycle of plugins and services. All the callbacks except for the "serve"
+service callback are invoked inside the ZIS address space. Depending on the
+service configuration the "serve" callback is invoked in either the caller's
+address space or the ZIS address space
+
+Plugin callbacks:
+* **init**: invoked upon ZIS startup
+* **term**: invoked upon ZIS termination
+* **command handler**: invoked when a ZIS modify command uses the plugin as its
+target
+
+Service callbacks:
+* **init**: invoked upon ZIS startup
+* **term**: invoked upon ZIS termination
+* **serve**: invoked when the service is called
+
+## Plugin lifecycle
+
+### ZIS startup
+For each plugin:
+* Load the plugin module into the ZIS A/S private storage
+* Call the entry point
+* Process the result `ZISPlugin` struct and relocate the plugin module to LPA if
+required (controlled by plugin parameters)
+* Call the plugin "init" function
+* For each plugin service, call the service "init" function
+
+When done ZIS sets the "ready" flag and accepts requests
+
+### ZIS termination
+First, ZIS unsets the "ready" flag and stops accepting requests.
+Then, for each plugin:
+* For each service, call the service "term" function
+* Call the plugin "term" function
+
+Any plugin module that has been loaded to LPA will remain in LPA.
+
+### Service call
+* ZIS looks up the service using the caller-specified plugin and service name
+* In the corresponding program call handler ZIS invokes the "serve" function of
+the service
+
+### z/OS operator modify command invocation
+* ZIS looks up the plugin using the modify command target, which is a plugin
+nickname
+* Call the command handler of the target plugin
+
+There are additional steps in dev mode which are described in the
+[Dev mode](#dev-mode) section.
+
+## Making a plugin
+
+This section will describe how to create a ZIS plugin using snippets from
+the sample plugin as examples. The sample plugin has a single service that
+returns the content of the control registers to a problem state caller (a simple
+LE client application). The register content is read using the `STCTG` HLASM
+instruction, which is a privileged operation and cannot be performed inside
+problem state applications.
+
+### Plugin descriptor
+
+A valid plugin must return the address of the [`ZISPlugin`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/plugin.h#L81-L112)
+struct describing the plugin itself and its services. That struct is created
+using the [`zisCreatePlugin`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/plugin.h#L139)
+function.
+
+Here's an example of how to use it:
+```c
+ZISPlugin *plugin = zisCreatePlugin(
+ (ZISPluginName) {SAMPLE_PLUGIN_NAME},
+ (ZISPluginNickname) {SAMPLE_PLUGIN_NICKNAME},
+ NULL, // plugin "init" function
+ NULL, // plugin "term" function
+ NULL, // plugin "modify command" handler
+ 1, // plugin version
+ 1, // number of services
+ ZIS_PLUGIN_FLAG_NONE // plugin flags
+);
+```
+
+For now the most important parameters are the plugin name, nickname, flags and
+version.
+
+##### Plugin name
+* Mapped by the [`ZISPluginName`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/plugin.h#L40)
+struct
+* A 16-character printable EBCDIC string
+* Uniquely identifies a plugin within ZIS
+##### Plugin nickname
+* Mapped by the [`ZISPluginNickname`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/plugin.h#L45)
+struct
+* A 4-character printable EBCDIC string
+* Uniquely identifies a plugin for modify commands within ZIS
+##### Plugin flags
+* Control various aspects of a plugin
+* By default, plugin modules are only loaded into the private ZIS storage, but
+when the [`ZIS_PLUGIN_FLAG_LPA`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/plugin.h#L63)
+flag is set, the module will be loaded to LPA
+##### Plugin version
+* ZIS uses the plugin version value to refresh the plugin module in LPA if
+needed, i.e. when a different version is detected, the current LPA module is
+discarded and the new version is loaded
+
+**IMPORTANT:** when any changes to a plugin or its service are made, the version
+must be incremented, so that the LPA module gets refreshed. During development
+process that can be avoided, see [LPA dev mode](#lpa-dev-mode).
+
+Please refer to the [`zisCreatePlugin` doc](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/plugin.h#L124-L138)
+for more details.
+
+### Plugin services
+
+Once we have our plugin descriptor, we can start creating and adding services to
+the plugin.
+
+A service can be created with the [`zisCreateService`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/service.h#L137)
+function.
+
+```c
+ZISService service = zisCreateService(
+ (ZISServiceName) {GETCR_SERVICE_NAME},
+ ZIS_SERVICE_FLAG_SPACE_SWITCH, // service flags
+ NULL, // service "init" function
+ NULL, // service "term" function
+ serveControlRegisters, // service "serve" function
+ 1 // service version
+);
+```
+
+The parameters we're interested in at the moment are the service name, flags
+and the "serve" function (see more details in [`zisCreateService` doc](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/service.h#L126-L136)
+).
+
+##### Service name
+* Mapped by the [`ZISServiceName`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/service.h#L42)
+struct
+* A 16-character printable EBCDIC string
+* Uniquely identifies a service within its plugin
+##### Service flags
+* Control various aspects of a service
+* By default, services are invoked in the PC-cp handler, to make a service
+space-switch, use `ZIS_SERVICE_FLAG_SPACE_SWITCH` (see details in [this](#pc-ss-vs-pc-cp-service)
+section)
+* You can also protect a service with an additional SAF check by setting the
+`ZIS_SERVICE_FLAG_SPECIFIC_AUTH` flag (see details in [this](#plugin-security)
+section)
+##### Service serve function
+* Invoked when a service is called
+* Depending on the type of the service, it's either invoked in the PC-ss or
+PC-cp ZIS handler (i.e. either the ZIS A/S or caller's primary A/S)
+
+After a service has been created, it should be added to the plugin descriptor
+using the [`zisPluginAddService`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/plugin.h#L164)
+function.
+
+### Putting it all together
+
+When you have finished building the plugin descriptor and added all the
+services, the descriptor should be returned from the entry point function of
+your plugin. Below is a full example of such an entry point.
+
+```c
+ZISPlugin *getPluginDescriptor(void) {
+
+ // this call will create a plugin data structure with the provided plugin
+ // name and nickname
+ ZISPlugin *plugin = zisCreatePlugin(
+ (ZISPluginName) {SAMPLE_PLUGIN_NAME},
+ (ZISPluginNickname) {SAMPLE_PLUGIN_NICKNAME},
+ NULL, // plugin "init" function
+ NULL, // plugin "term" function
+ NULL, // plugin "modify command" handler
+ 1, // plugin version
+ 1, // number of services
+ ZIS_PLUGIN_FLAG_NONE // plugin flags
+ );
+ if (plugin == NULL) {
+ return NULL;
+ }
+
+ // add a single service to our plugin
+ ZISService service = zisCreateService(
+ (ZISServiceName) {GETCR_SERVICE_NAME},
+ ZIS_SERVICE_FLAG_SPACE_SWITCH, // service flags
+ NULL, // service "init" function
+ NULL, // service "term" function
+ serveControlRegisters, // service "serve" function
+ 1 // service version
+ );
+ int addRC = zisPluginAddService(plugin, service);
+ if (addRC != RC_ZIS_PLUGIN_OK) {
+ zisDestroyPlugin(plugin);
+ return NULL;
+ }
+
+ return plugin;
+}
+```
+
+## Building a plugin
+
+To build your plugin only the plugin sources will need to be compiled and
+assembled. Considering the [dynamic linkage](#dynamic-linkage-stub) is used, all
+the [zss](https://github.com/zowe/zss) and [zowe-common-c](https://github.com/zowe/zowe-common-c)
+functionality will be available dynamically and only the corresponding headers
+will be needed.
+
+### Compilation
+
+Plugin sources are compiler using the XL C/C++ compiler.
+
+#### Compiler requirements
+* Metal C (`-S -qmetal -DMETTLE=1`)
+* 64-bit (`-q64`)
+* Reserved GPR12 (`-qreserved_reg=r12`)
+* Read-only constants (`-qroconst`)
+* Long names (`-qlongname`)
+
+### Assembly
+
+Plugin objects are built using the `as` tool.
+
+#### Assembler requirements
+* GOFF (`-mgoff`)
+* Produce object (`-mobject`)
+
+#### Recommended options
+* Check reenterability (`--RENT`)
+
+### Linking
+
+Plugin modules are linked using the `ld` linker.
+
+#### Linker requirement
+* Reenterable (`-b reus=rent`)
+* Mixed case (`-b case=mixed`)
+
+**There is no requirement to link-edit plugin load modules with AC(1).**
+
+You can find the complete build script with all the options in the sample plugin
+(see [`zss/plugins/zis/sample/build.sh`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/plugins/zis/sample/build.sh)
+).
+
+### Dynamic linkage stub
+
+Starting from Zowe v2.4 ZIS plugins can use dynamic linkage. That is achieved
+by linking plugin modules with a special HLASM-based stub. The stub is
+generated using the tools in [`zss/tools/dynzis`](https://github.com/zowe/zss/tree/82c6f2d30951d64fb1bb6487c2dde92700b91552/tools/dynzis).
+
+An example of how to generate the stub.
+```shell
+# build the tool
+javac -encoding iso8859-1 zss/tools/dynzis/org/zowe/zis/ZISStubGenerator.java
+# generate the stub HLASM
+java -cp zss/tools/dynzis org.zowe.zis.ZISStubGenerator asm zss/h/zis/zisstubs.h > dynzis.s
+```
+
+Once the stub has been generated, assemble and link it with your plugin objects.
+
+See [zss/tools/dynzis/README.md](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/tools/dynzis/README.md)
+for more details.
+
+## Deploying a plugin
+
+Put the plugin module in a data set in the ZIS STEPLIB concatenation and add
+the following line to the ZIS PARMLIB member:
+```
+ZWES.PLUGIN.id=module_name
+```
+
+Where
+* `id` is a string with no blanks, which is unique within the `ZWES.PLUGIN`
+scope in your config member
+* `module_name` is the module name of your plugin
+
+### Dynamic linkage considerations
+
+If your plugin utilizes the dynamic linkage, the dynamic linkage plugin must
+also be added to the config.
+
+Add the following line to the config member to enable the dynamic linkage
+plugin:
+```
+ZWES.PLUGIN.DYNL=ZWESISDL
+```
+
+## Plugin details
+
+### Serve function environment
+
+Depending on the caller, the "serve" function is invoked in the following
+environment:
+* Authorization: key 4 and supervisor state
+* Dispatchable unit mode: task or SRB
+* Cross memory mode:
+ * If PC-ss, PASN will point to ZIS A/S and SASN will point to the caller's A/S
+ * If PC-cp, both PASN and SASN will point to the caller's A/S
+* AMODE: 64-bit
+* ASC mode: primary
+* Interrupt status: enabled or disabled for I/O and external interrupts
+* Locks: any lock except CMS or no locks held
+* Active RLE environment
+ * Recovery context is established (either ESTAE or FRR depending on the
+ environment) and recovery functionality is available using [`recoveryPush`](https://github.com/zowe/zowe-common-c/blob/4f2732d0e781aec89b39f862262d5014a97c09b7/h/recovery.h#L487)
+ and [`recoveryPop`](https://github.com/zowe/zowe-common-c/blob/4f2732d0e781aec89b39f862262d5014a97c09b7/h/recovery.h#L503)
+ * No logging context is created but logging is available using [`cmsPrintf`](https://github.com/zowe/zowe-common-c/blob/4f2732d0e781aec89b39f862262d5014a97c09b7/h/crossmemory.h#L517)
+
+### Other callbacks' environment
+
+The plugin and service "init", "term" functions and the plugin
+"command handler" function are invoked in the following environment:
+* Authorization: APF-authorized, key 4 and problem state
+* Dispatchable unit mode: task
+* Cross memory mode: HASN=PASN=SASN
+* AMODE: 64-bit
+* ASC mode: primary
+* Interrupt status: enabled for I/O and external interrupts
+* Locks: no locks held
+* Active RLE environment
+ * Recovery context is established (ESTAE) and recovery functionality is
+ available using [`recoveryPush`](https://github.com/zowe/zowe-common-c/blob/4f2732d0e781aec89b39f862262d5014a97c09b7/h/recovery.h#L487)
+ and [`recoveryPop`](https://github.com/zowe/zowe-common-c/blob/4f2732d0e781aec89b39f862262d5014a97c09b7/h/recovery.h#L503)
+ * Logging context is created and logging is available using [`zowelog`](https://github.com/zowe/zowe-common-c/blob/4f2732d0e781aec89b39f862262d5014a97c09b7/h/logging.h#L337)
+
+#### User parameter list
+
+ZIS will pass the address of the caller's parameter list in the caller's primary
+address space to the service "serve" function. However, it will be opaque. The
+plugin developer and the client need to agree of the parameter list format.
+
+Here are some guidelines:
+* Include an eye-catcher field which can be later validated by the service
+* Include a version field for compatibility
+* Make sure the parameter list has the same layout and size in Metal C 31-bit,
+Metal C 64-bit, LE 31-bit, etc. That can be done using `__packed` or the [`ZOWE_PARGMA_PACK`/`ZOWE_PRAGMA_PACK_RESET` macros](https://github.com/zowe/zowe-common-c/blob/4f2732d0e781aec89b39f862262d5014a97c09b7/h/zowetypes.h#L178-L179).
+
+The following is an example of a parameter list taken from the sample:
+```c
+typedef __packed struct GetCRServiceParm_tag {
+#define GETCR_SERVICE_PARM_EYECATCHER "GETCRPRM"
+#define GETCR_SERVICE_PARM_VERSION 1
+ char eyecatcher[8];
+ uint8_t version;
+ ControlRegisters result;
+} GetCRServiceParm;
+```
+
+#### Accessing caller's data
+
+All the virtual storage from the caller's address space, including the parameter
+list, must be read using the [`cmCopyFromSecondaryWithCallerKey`](https://github.com/zowe/zowe-common-c/blob/4f2732d0e781aec89b39f862262d5014a97c09b7/h/cmutils.h#L104)
+function and written to using the [`cmCopyToSecondaryWithCallerKey`](https://github.com/zowe/zowe-common-c/blob/4f2732d0e781aec89b39f862262d5014a97c09b7/h/cmutils.h#L92)
+function. Among other things, this will ensure that a malicious caller will not
+use ZIS to access storage using ZIS'es privileged key.
+
+An example of how to copy a parameter list and return results:
+```c
+
+void *serviceParmList = ...; // parameter list in the caller's A/S
+GetCRServiceParm localParmList; // parameter list in the primary A/S
+
+cmCopyFromSecondaryWithCallerKey(&localParmList, serviceParmList,
+ sizeof(localParmList));sa
+. . .
+cmCopyToSecondaryWithCallerKey(serviceParmList, &localParmList,
+ sizeof(localParmList));
+```
+
+#### Function return codes
+
+Your "serve" function must return [`RC_ZIS_SRVC_OK`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/service.h#L201)
+in case of success and for any other return values the value larger than
+[`ZIS_MAX_GEN_SRVC_RC`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/service.h#L215)
+must be used.
+
+For example:
+```c
+#define RC_GETCR_OK RC_ZIS_SRVC_OK
+#define RC_GETCR_BAD_EYECATCHER (ZIS_MAX_GEN_SRVC_RC + 1)
+#define RC_GETCR_BAD_VERSION (ZIS_MAX_GEN_SRVC_RC + 2)
+```
+
+The values in the range (`RC_ZIS_SRVC_OK`, `ZIS_MAX_GEN_SRVC_RC`] are reserved.
+
+### PC-ss vs PC-cp service
+
+Depending on the nature of your service, set the [`ZIS_SERVICE_FLAG_SPACE_SWITCH`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/service.h#L96)
+flag so that the service is invoked in either the PC-ss or PC-cp ZIS program
+call handler. The main differences between PC-ss and PC-cp are described below.
+
+| Feature | PC-ss | PC-cp | Examples |
+|---------------------------------------------------------------|-------|-------|---------------------------------------|
+| Access to resources inside or owned by ZIS A/S | Yes | No | Allocating storage inside the ZIS A/S |
+| Code isolation | Yes | No | |
+| Service code in private storage 1 | Yes | No | |
+| Execute services that are not supported in cross-memory mode | No | Yes | Calling an SVC, performing basic I/O |
+
+##### Notes
+1. The code used by a PC-cp service must be in commonly addressable storage
+(to facilitate that ZIS can automatically place the plugin module in LPA, see
+[`ZIS_PLUGIN_FLAG_LPA`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/plugin.h#L90))
+
+### Plugin security
+
+Every ZIS caller must have READ access to the "ZWES.IS" profile in the "FACILITY"
+class. In addition to that, plugin developers can add another SAF check via
+the [`zisServiceUseSpecificAuth`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/service.h#L187) function.
+
+First, set the [`ZIS_SERVICE_FLAG_SPECIFIC_AUTH`](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/service.h#L97)
+flag when creating a service, then call `zisServiceUseSpecificAuth` to set the
+SAF profile to which you wish the callers' READ access to be checked
+when calling the service.
+
+The SAF profile must be in a RACLISTed class, that is, be present in virtual
+storage as opposed to just being in the RACF database on disk.
+
+## Dev mode
+
+When loading a new version of a plugin ZIS discards the previous version of
+the plugin module and never deletes it from LPA. This is done for security and
+integrity reasons. However, during development process you usually rebuild your
+plugin multiple times and that would be wasteful to always leave the old version
+in LPA, because LPA is a very limited resource. To prevent LPA exhaustion and
+avoid wasting some other common resources ZIS has introduced various development
+modes.
+
+**IMPORTANT:** never use the development modes in production as they might lead
+to system integrity exposures.
+
+### General ZIS dev mode
+
+This is a dev mode which when enabled will include the following modes:
+* [LPA dev mode](#lpa-dev-mode)
+
+To enable the general ZIS dev mode, add the following line to the config member:
+```
+ZWES.DEV_MODE=YES
+```
+
+### LPA dev mode
+
+When the LPA dev mode is on, at startup and termination ZIS will remove the old
+version of the ZIS load module and any plugin modules from LPA.
+
+To enable the LPA dev mode, add the following line to the config member:
+```
+ZWES.DEV_MODE.LPA=YES
+```
+
+You should see the following messages IDs when the dev mode is on:
+* [ZWES0247W](https://github.com/zowe/zowe-common-c/blob/4f2732d0e781aec89b39f862262d5014a97c09b7/h/crossmemory.h#L1043-L1047)
+* [ZWES0213W](https://github.com/zowe/zss/blob/82c6f2d30951d64fb1bb6487c2dde92700b91552/h/zis/message.h#L303-L305)
+(if the dynamic linkage plugin is used)
+
+Additionally, the dynamic linkage plugin will remove its old stub vector from
+common storage, since it can no longer reference the old LPA plugin module.
+
+___
+
+This program and the accompanying materials are
+made available under the terms of the Eclipse Public License v2.0 which accompanies
+this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html
+
+SPDX-License-Identifier: EPL-2.0
+
+Copyright Contributors to the Zowe Project.
diff --git a/plugins/zis/sample/README.md b/plugins/zis/sample/README.md
new file mode 100644
index 000000000..48f57955e
--- /dev/null
+++ b/plugins/zis/sample/README.md
@@ -0,0 +1,50 @@
+This program and the accompanying materials are
+made available under the terms of the Eclipse Public License v2.0 which accompanies
+this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html
+
+SPDX-License-Identifier: EPL-2.0
+
+Copyright Contributors to the Zowe Project.
+___
+
+# ZIS sample plugin
+
+## Build
+
+Run the following command to build both the plugin and the client application:
+```shell
+> ./build.sh
+```
+
+The plugin module `ZISSAMPL` will be placed into the `user_name.DEV.LOADLIB`
+data set and the client binary will be stored in `./bin`.
+
+## Deploy
+
+* Make sure the plugin module is in a data sets which is part of the STEPLIB
+concatenation of your ZIS.
+* Add the following line to your ZIS PARMLIB config member:
+```
+ZWES.PLUGIN.SMPL=ZISSAMPL
+```
+* Additionally, make sure you have the dynamic linkage plugin in your config:
+```
+ZWES.PLUGIN.DYNL=ZWESISDL
+```
+
+## Run
+
+* Restart your ZIS
+* Run the client with the ZIS name as the argument
+```shell
+> ./bin/sample_client
+```
+___
+
+This program and the accompanying materials are
+made available under the terms of the Eclipse Public License v2.0 which accompanies
+this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html
+
+SPDX-License-Identifier: EPL-2.0
+
+Copyright Contributors to the Zowe Project.
diff --git a/plugins/zis/sample/build.sh b/plugins/zis/sample/build.sh
new file mode 100755
index 000000000..18edf62c2
--- /dev/null
+++ b/plugins/zis/sample/build.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+set -e
+
+# This program and the accompanying materials are
+# made available under the terms of the Eclipse Public License v2.0 which accompanies
+# this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+# Copyright Contributors to the Zowe Project.
+
+ZSS=../../../../../zss
+COMMON=$ZSS/deps/zowe-common-c
+
+# compile, assembler and linker flags for the sample plugin
+CFLAGS="-S -qmetal -DMETTLE=1 -q64 -qreserved_reg=r12 -qroconst -qlongname"
+ASFLAGS="-mgoff -mobject --RENT"
+LDFLAGS="-b reus=rent -b case=mixed"
+CFLAGS_INFO="-qlist= -qaggregate -qexpmac -qsource -qoffset -qxref"
+LDFLAGS_INFO="-V -b map -b xref"
+
+PLUGIN_INCLUDES="-I ${COMMON}/h -I ${ZSS}/h -I ."
+
+# build the sample plugin
+# - build the java generator tool and generate the HLASM stubs for dynamic linkage
+# - build the plugin itself
+mkdir -p tmp_plugin
+cd tmp_plugin
+
+javac -encoding iso8859-1 ${ZSS}/tools/dynzis/org/zowe/zis/ZISStubGenerator.java
+java -cp ${ZSS}/tools/dynzis org.zowe.zis.ZISStubGenerator asm \
+ ${ZSS}/h/zis/zisstubs.h > dynzis.s
+
+xlc ${CFLAGS} ${CFLAGS_INFO} ${PLUGIN_INCLUDES} \
+ $ZSS/plugins/zis/sample/sample_plugin.c
+as ${ASFLAGS} -aegimrsx=sample_plugin.asm sample_plugin.s
+as ${ASFLAGS} -aegimrsx=dynzis.asm dynzis.s
+ld ${LDFLAGS} ${LDFLAGS_INFO} -e getPluginDescriptor \
+-o "//'$USER.DEV.LOADLIB(ZISSAMPL)'" \
+sample_plugin.o dynzis.o > sample_plugin.link
+cd ..
+
+# build the sample client
+mkdir -p tmp_client
+mkdir -p bin
+cd tmp_client
+xlc "-Wa,goff" \
+"-Wc,langlvl(extc99),asm,asmlib('SYS1.MACLIB'),lp64,xplink" \
+-DCMS_CLIENT -D_OPEN_THREADS=1 -I $COMMON/h -I $ZSS/h \
+${COMMON}/c/alloc.c \
+${COMMON}/c/cmutils.c \
+${COMMON}/c/crossmemory.c \
+${COMMON}/c/timeutls.c \
+${COMMON}/c/utils.c \
+${COMMON}/c/zos.c \
+${COMMON}/c/zvt.c \
+${ZSS}/c/zis/client.c \
+-o ../bin/sample_client ../sample_client.c
+cd ..
+
+# This program and the accompanying materials are
+# made available under the terms of the Eclipse Public License v2.0 which accompanies
+# this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+# Copyright Contributors to the Zowe Project.
diff --git a/plugins/zis/sample/sample_client.c b/plugins/zis/sample/sample_client.c
new file mode 100644
index 000000000..58b3b5878
--- /dev/null
+++ b/plugins/zis/sample/sample_client.c
@@ -0,0 +1,64 @@
+/*
+ This program and the accompanying materials are
+ made available under the terms of the Eclipse Public License v2.0 which accompanies
+ this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html
+
+ SPDX-License-Identifier: EPL-2.0
+
+ Copyright Contributors to the Zowe Project.
+*/
+
+#include
+#include
+
+#include "zis/client.h"
+
+#include "sample_plugin.h"
+
+int main(int argc, char **argv) {
+
+ if (argc < 2) {
+ printf("error: too few parameters\n");
+ printf("usage: > sample_client \n");
+ exit(EXIT_FAILURE);
+ }
+
+ GetCRServiceParm parmList = {
+ .eyecatcher = GETCR_SERVICE_PARM_EYECATCHER,
+ .version = GETCR_SERVICE_PARM_VERSION,
+ };
+
+ CrossMemoryServerName xmemName = cmsMakeServerName(argv[1]);
+ ZISServicePath servicePath = {
+ .pluginName = SAMPLE_PLUGIN_NAME,
+ .serviceName = GETCR_SERVICE_NAME,
+ };
+ ZISServiceStatus status;
+
+ int callRC = zisCallService(&xmemName, &servicePath, &parmList, &status);
+ if (callRC == RC_GETCR_OK) {
+ printf("info: successfully called the \'%s\' service:\n",
+ GETCR_SERVICE_NAME);
+ size_t crCount = sizeof(parmList.result.reg) / sizeof(parmList.result.reg[0]);
+ for (size_t regIdx = 0; regIdx < crCount; regIdx++) {
+ printf(" CR%-2zu = 0x%016llX\n", regIdx, parmList.result.reg[regIdx]);
+ }
+ exit(EXIT_SUCCESS);
+ } else {
+ printf("error: service call failed - call RC = %d, "
+ "service RC = %d, CMS RC = %d\n", callRC,
+ status.serviceRC, status.cmsRC);
+ exit(EXIT_FAILURE);
+ }
+
+}
+
+/*
+ This program and the accompanying materials are
+ made available under the terms of the Eclipse Public License v2.0 which accompanies
+ this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html
+
+ SPDX-License-Identifier: EPL-2.0
+
+ Copyright Contributors to the Zowe Project.
+*/
\ No newline at end of file
diff --git a/plugins/zis/sample/sample_plugin.c b/plugins/zis/sample/sample_plugin.c
new file mode 100644
index 000000000..e2067f8f7
--- /dev/null
+++ b/plugins/zis/sample/sample_plugin.c
@@ -0,0 +1,145 @@
+/*
+ This program and the accompanying materials are
+ made available under the terms of the Eclipse Public License v2.0 which accompanies
+ this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html
+
+ SPDX-License-Identifier: EPL-2.0
+
+ Copyright Contributors to the Zowe Project.
+*/
+
+#include
+#include
+#include
+
+#include "zowetypes.h"
+#include "cmutils.h"
+#include "zis/plugin.h"
+
+#include "sample_plugin.h"
+
+// forward declaration of the "serve" function
+static int serveControlRegisters(const CrossMemoryServerGlobalArea *ga,
+ ZISServiceAnchor *anchor,
+ ZISServiceData *data,
+ void *serviceParmList);
+
+ZISPlugin *getPluginDescriptor(void) {
+
+ // this call will create a plugin data structure with the provided plugin
+ // name and nickname
+ ZISPlugin *plugin = zisCreatePlugin(
+ (ZISPluginName) {SAMPLE_PLUGIN_NAME},
+ (ZISPluginNickname) {SAMPLE_PLUGIN_NICKNAME},
+ NULL, // plugin "init" function
+ NULL, // plugin "term" function
+ NULL, // plugin "modify command" handler
+ 1, // plugin version
+ 1, // number of services
+ ZIS_PLUGIN_FLAG_NONE // plugin flags
+ );
+ if (plugin == NULL) {
+ return NULL;
+ }
+
+ // add a single service to our plugin
+ ZISService service = zisCreateService(
+ (ZISServiceName) {GETCR_SERVICE_NAME},
+ ZIS_SERVICE_FLAG_SPACE_SWITCH, // service flags
+ NULL, // service "init" function
+ NULL, // service "term" function
+ serveControlRegisters, // service "serve" function
+ 1 // service version
+ );
+ int addRC = zisPluginAddService(plugin, service);
+ if (addRC != RC_ZIS_PLUGIN_OK) {
+ zisDestroyPlugin(plugin);
+ return NULL;
+ }
+
+ return plugin;
+}
+
+// forward declaration of the helper functions
+static int verifyGetCRServiceParmList(const GetCRServiceParm *parmList);
+void getControlRegisters(ControlRegisters *result);
+
+/**
+ * This is the "serve" function of the "get CR" service. It will be invoked by
+ * the cross-memory server once the respective service is called.
+ * @param[in] ga the cross-memory server's global area.
+ * @param[in,out] anchor the ZIS anchor provided by the cross-memory server.
+ * @param[in,out] data the service data provided by the cross-memory server.
+ * @param[in,out] serviceParmList the parameter list from the caller.
+ * @return the service's return code.
+ */
+static int serveControlRegisters(const CrossMemoryServerGlobalArea *ga,
+ ZISServiceAnchor *anchor,
+ ZISServiceData *data,
+ void *serviceParmList) {
+
+ // since the caller's parameter list is in a different address space, we
+ // have to copy it to a local variable using a special copy function
+ GetCRServiceParm localParmList;
+ cmCopyFromSecondaryWithCallerKey(&localParmList, serviceParmList,
+ sizeof(localParmList));
+
+ // it's good practice to validate the parameter list
+ // see all the details in the helper function
+ int verifyRC = verifyGetCRServiceParmList(&localParmList);
+ if (verifyRC != RC_GETCR_OK) {
+ return verifyRC;
+ }
+
+ // now, let's perform a privileged operation and extract the control registers
+ getControlRegisters(&localParmList.result);
+
+ // finally, we need to return the result to the caller by copying the updated
+ // parameter list to the caller's address space
+ cmCopyToSecondaryWithCallerKey(serviceParmList, &localParmList,
+ sizeof(localParmList));
+
+ return RC_GETCR_OK;
+}
+
+/**
+ * Verify the "get CR" service's parameter list.
+ * @param parmList the parameter list to be verified.
+ * @return @c RC_GETCR_OK in case of success and the corresponding
+ * RC_GETCR_XXXX value in case of failure.
+ */
+static int verifyGetCRServiceParmList(const GetCRServiceParm *parmList) {
+ if (memcmp(parmList->eyecatcher, GETCR_SERVICE_PARM_EYECATCHER,
+ sizeof(parmList->eyecatcher))) {
+ return RC_GETCR_BAD_EYECATCHER;
+ }
+ if (parmList->version != GETCR_SERVICE_PARM_VERSION) {
+ return RC_GETCR_BAD_VERSION;
+ }
+ return RC_GETCR_OK;
+}
+
+/**
+ * Extract the content of the control registers.
+ * @param[out] result the 64-bit value from CR.
+ */
+void getControlRegisters(ControlRegisters *resultRegisters) {
+ ControlRegisters regs __attribute__((aligned(8))) = {0};
+ __asm(
+ " STCTG 0,15,%[result] \n"
+ : [result]"=m"(regs)
+ :
+ :
+ );
+ *resultRegisters = regs;
+}
+
+/*
+ This program and the accompanying materials are
+ made available under the terms of the Eclipse Public License v2.0 which accompanies
+ this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html
+
+ SPDX-License-Identifier: EPL-2.0
+
+ Copyright Contributors to the Zowe Project.
+*/
\ No newline at end of file
diff --git a/plugins/zis/sample/sample_plugin.h b/plugins/zis/sample/sample_plugin.h
new file mode 100644
index 000000000..b40da0298
--- /dev/null
+++ b/plugins/zis/sample/sample_plugin.h
@@ -0,0 +1,49 @@
+/*
+ This program and the accompanying materials are
+ made available under the terms of the Eclipse Public License v2.0 which accompanies
+ this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html
+
+ SPDX-License-Identifier: EPL-2.0
+
+ Copyright Contributors to the Zowe Project.
+*/
+
+#ifndef PLUGINS_ZIS_SAMPLE_PLUGIN_H
+#define PLUGINS_ZIS_SAMPLE_PLUGIN_H
+
+// these are the codes returned by the "get CR" service
+// the success return code must be equal to @c RC_ZIS_SRVC_OK and any other
+// return codes must have values larger than @c ZIS_MAX_GEN_SRVC_RC
+#define RC_GETCR_OK RC_ZIS_SRVC_OK
+#define RC_GETCR_BAD_EYECATCHER (ZIS_MAX_GEN_SRVC_RC + 1)
+#define RC_GETCR_BAD_VERSION (ZIS_MAX_GEN_SRVC_RC + 2)
+
+#define SAMPLE_PLUGIN_NAME "SAMPLE "
+#define SAMPLE_PLUGIN_NICKNAME "SMPL"
+
+#define GETCR_SERVICE_NAME "GET_CTRL_REGS "
+
+typedef __packed struct ControlRegisters_tag {
+ uint64_t reg[16];
+} ControlRegisters;
+
+/**
+ * This struct describes the parameter list of the "get CR" service.
+ */
+typedef __packed struct GetCRServiceParm_tag {
+#define GETCR_SERVICE_PARM_EYECATCHER "GETCRPRM"
+#define GETCR_SERVICE_PARM_VERSION 1
+ char eyecatcher[8];
+ uint8_t version;
+ ControlRegisters result;
+} GetCRServiceParm;
+
+#endif //PLUGINS_ZIS_SAMPLE_PLUGIN_H
+
+/*
+ This program and the accompanying materials are
+ made available under the terms of the Eclipse Public License v2.0 which accompanies
+ this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html
+ SPDX-License-Identifier: EPL-2.0
+ Copyright Contributors to the Zowe Project.
+*/
diff --git a/tests/build_zisdl.sh b/tests/build_zisdl.sh
old mode 100644
new mode 100755
index 29882af48..4264eabf1
--- a/tests/build_zisdl.sh
+++ b/tests/build_zisdl.sh
@@ -1,11 +1,4 @@
#!/bin/sh
-#
-# OMEGAMON Open Data
-# V1R1M0
-# 5698-B6603 © Copyright Rocket Software, Inc. or its affiliates. 2021.
-# All rights reserved.
-#
-
set -e
################################################################################
@@ -25,15 +18,18 @@ COMMON="../../deps/zowe-common-c"
echo "********************************************************************************"
echo "Building ZIS Dynamic Linkage test..."
-mkdir -p "${WORKING_DIR}/tmp-zisdl" && cd "$_"
+mkdir -p "${WORKING_DIR}/tmp-zisdl"
+cd ${WORKING_DIR}/tmp-zisdl
+
+javac -encoding iso8859-1 ${ZSS}/tools/dynzis/org/zowe/zis/ZISStubGenerator.java
+java -cp ${ZSS}/tools/dynzis org.zowe.zis.ZISStubGenerator asm \
+ ${ZSS}/h/zis/zisstubs.h > stubs.s
xlc -S -M -qmetal -q64 -DMETTLE=1 \
-qreserved_reg=r12 \
-Wc,arch\(8\),agg,exp,list\(\),so\(\),off,xref,roconst,longname,lp64 \
-I ${COMMON}/h -I ${ZSS}/h ../zisdl.c
-cp ${ZSS}/c/zis/stubs.s .
-
for file in \
zisdl stubs
do
diff --git a/version.txt b/version.txt
index 197c4d5c2..437459cd9 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-2.4.0
+2.5.0