- Perform a full system save, like GO SAVE, option 21.
- Apply all microcode PTFs permanently.
- Load the TR PTF and set it to be applied temporarily.
- IPL the system.
- Apply the TR PTF permanently.
- Unloaded the microcode PTFs set for delayed apply, except for those that were pre-requisites to MF99002.
- Performed a full system save.
- IPLed the system to apply the pre-requiste microcode PTFs.
- Permanently applied all microcode PTFs.
- Loaded MF99002 and set it to delayed apply.
- IPLed the system.
- Permanently applied MF99002.
- Loaded the rest of the microcode PTFs and set them to delayed apply.
- IPLed the system.
After that first IPL it would find that the TR PTF wasn't loaded yet, so it would apply all microcode PTFs permanently, load the TR PTF, set it to delayed apply, and IPL. When the system came up again it would find that the TR PTF was applied. It would then permanently apply it, load the rest of the microcode PTFs sitting in *SERVICE, set them to be applied delayed, and IPL again.
I've included the code below:
/******************************************************************************/ /* Program....: APYTRPTF */ /* Description: Apply technology refresh PTF. */ /* Author.....: Joe Code */ /* Date.......: 02/18/2011 */ /* */ /* Create */ /* ------ */ /* CRTCLMOD DBGVIEW(*ALL) */ /* CRTPGM USRPRF(*OWNER) AUT(*EXCLUDE) */ /* CHGOBJOWN OBJTYPE(*PGM) NEWOWN(QSECOFR) */ /* GRTOBJAUT OBJTYPE(*PGM) USER(QPGMR) AUT(*USE) */ /* */ /* License */ /* ------- */ /* This library is free software; you can redistribute it and/or modify it */ /* under the terms of the GNU Lesser General Public License as published by */ /* the Free Software Foundation; either version 2.1 of the License, or (at */ /* your option) any later version. (Unlike the normal GNU GPL, the "lesser" */ /* GPL allows libraries to be used in commercial/proprietary software.) */ /* */ /* This library is distributed in the hope that it will be useful, but */ /* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT- */ /* ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General */ /* Public License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with this library; if not, write to the Free Software Foundation, */ /* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* (http://www.gnu.org/licenses/lgpl.html#SEC3) */ /******************************************************************************/ PGM COPYRIGHT TEXT('Copyright (c) 2011 Joe Code') DCL VAR(&COUNT) TYPE(*DEC) LEN(3 0) DCL VAR(&ERROR) TYPE(*LGL) VALUE('0') DCL VAR(&RCVVARLEN) TYPE(*INT) LEN(4) VALUE(131) DCL VAR(&PTFINFO) TYPE(*CHAR) LEN(50) DCL VAR(&PTFID) TYPE(*CHAR) LEN(7) STG(*DEFINED) DEFVAR(&PTFINFO 1) DCL VAR(&PRODID) TYPE(*CHAR) LEN(7) STG(*DEFINED) DEFVAR(&PTFINFO 8) DCL VAR(&RLSLVL) TYPE(*CHAR) LEN(6) STG(*DEFINED) DEFVAR(&PTFINFO 15) DCL VAR(&CCSID) TYPE(*INT) LEN(4) STG(*DEFINED) DEFVAR(&PTFINFO 21) DCL VAR(&CLSPTFF) TYPE(*CHAR) LEN(1) STG(*DEFINED) DEFVAR(&PTFINFO 25) DCL VAR(&RESERVED) TYPE(*CHAR) LEN(25) STG(*DEFINED) DEFVAR(&PTFINFO 26) DCL VAR(&RCVVAR) TYPE(*CHAR) LEN(131) DCL VAR(&BYTESRTN) TYPE(*INT) LEN(4) STG(*DEFINED) DEFVAR(&RCVVAR 1) DCL VAR(&BYTESAVL) TYPE(*INT) LEN(4) STG(*DEFINED) DEFVAR(&RCVVAR 5) DCL VAR(&LOADEDSTS) TYPE(*CHAR) LEN(1) STG(*DEFINED) DEFVAR(&RCVVAR 41) DCL VAR(&IPLACTION) TYPE(*CHAR) LEN(1) STG(*DEFINED) DEFVAR(&RCVVAR 66) MONMSG MSGID(CPF0000 CEE0000 MCH0000) EXEC(GOTO CMDLBL(ERROR)) QSYS/CHKOBJ OBJ(QGPL/APYTRPTF) OBJTYPE(*DTAARA) MONMSG MSGID(CPF9801) EXEC(QSYS/CRTDTAARA DTAARA(QGPL/APYTRPTF) + TYPE(*DEC) LEN(3 0) VALUE(0) TEXT('Stop infinite loop if error + applying TR PTF.')) QSYS/RTVDTAARA DTAARA(QGPL/APYTRPTF) RTNVAR(&COUNT) CHGVAR VAR(&COUNT) VALUE(&COUNT + 1) QSYS/CHGDTAARA DTAARA(QGPL/APYTRPTF) VALUE(&COUNT) CHGVAR VAR(&PTFID) VALUE('MF99002') CHGVAR VAR(&PRODID) VALUE('5770999') CHGVAR VAR(&RLSLVL) VALUE('V7R1M0') CHGVAR VAR(&CCSID) VALUE(0) /* Use job's CCSID. */ CHGVAR VAR(&CLSPTFF) VALUE('0') /* Close PTF files afterwards. */ CHGVAR VAR(&RESERVED) VALUE(' ') QSYS/CALL PGM(QSYS/QPZRTVFX) PARM(&RCVVAR &RCVVARLEN &PTFINFO + 'PTFR0100' X'00000000') SELECT WHEN COND(&BYTESRTN < &RCVVARLEN *OR &BYTESAVL < &RCVVARLEN) + THEN(QSYS/SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('No data + returned') TOPGMQ(*PRV (*PGMBDY)) MSGTYPE(*ESCAPE)) WHEN COND(&LOADEDSTS = '0') THEN(DO) /* Not loaded? */ IF COND(&COUNT = 1) THEN(DO) QSYS/APYPTF LICPGM(5770999) APY(*PERM) MONMSG MSGID(CPF3660) /* No PTFs identified. */ QSYS/LODPTF LICPGM(5770999) SELECT(MF99002) QSYS/APYPTF LICPGM(5770999) SELECT(MF99002) DELAYED(*YES) QSYS/PWRDWNSYS OPTION(*IMMED) RESTART(*YES) IPLSRC(B) ENDDO ENDDO WHEN COND(&LOADEDSTS = '1') THEN(DO) /* Loaded, but not applied? */ IF COND(&COUNT = 1) THEN(DO) QSYS/APYPTF LICPGM(5770999) APY(*PERM) MONMSG MSGID(CPF3660) /* No PTFs identified. */ IF COND(&IPLACTION = '0') THEN(QSYS/APYPTF LICPGM(5770999) + SELECT(MF99002) DELAYED(*YES)) /* IPL action isn't set? + Then set it. */ QSYS/PWRDWNSYS OPTION(*IMMED) RESTART(*YES) IPLSRC(B) ENDDO ENDDO WHEN COND(&LOADEDSTS = '2') THEN(DO) /* Temporarily applied? */ IF COND(&COUNT = 2) THEN(DO) QSYS/APYPTF LICPGM(5770999) SELECT(MF99002) APY(*PERM) QSYS/LODPTF LICPGM(5770999) MONMSG MSGID(CPF35A8) /* No PTFs to be loaded. */ QSYS/APYPTF LICPGM(*ALL) DELAYED(*YES) MONMSG MSGID(CPF3660) /* No PTFs identified. */ QSYS/PWRDWNSYS OPTION(*IMMED) RESTART(*YES) IPLSRC(B) ENDDO ENDDO ENDSELECT RETURN /******************************************************************************/ /* */ ERROR: /* Global error handling section. */ /* */ /******************************************************************************/ IF COND(&ERROR) THEN(RETURN) /* Prevents an infinite loop if an error */ CHGVAR VAR(&ERROR) VALUE('1') /* occurs within the error handling section. */ QSYS/SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Unexpected error + occurred. See previous messages') TOPGMQ(*PRV (*PGMBDY)) MSGTYPE(*ESCAPE) ENDPGM
On our small system this program added an extra two hours to the normal weekend backup/IPL. The only problem I ran into was that the microcode PTFs that I removed weren't loaded again. Apparently when you permanently remove a microcode PTF, it's also removed from the list of "*ALL PTFs in *SERVICE", meaning they can't be loaded when you specify LODPTF DEV(*SERVICE) SELECT(*ALL). You have to specifically name them in the SELECT parameter. Next week when I do this again I am going to load all of the microcode PTFs and leave the delayed apply flags shut off. (Except of course for the TR PTF's pre-requisites.)
Looking at the program again this morning I realized that if there was a subtle problem with applying the TR PTF then it might cause an infinite loop of IPLing, which would be very bad. I've since changed the program to include a safety valve in the form of a data area used to count the number of IPLs. If the count doesn't match up with what is supposed to happen then it doesn't do anymore IPLs. This amended version of the program compiles, but I haven't tested it yet. If you want to wait, it will be tested again next weekend when I apply the TR PTF to another system in our network. I will update this post with the results.
Update (2011-02-28): This version of the program did it's job and applied the TR PTF without error.
Update (2011-06-07): IBM has since issued PTFs to make this task easier, so it would seem that the program above is obsolete.