1 package org.metricshub.ipmi.core.coding.payload.lan;
2
3 /*-
4 * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5 * IPMI Java Client
6 * ჻჻჻჻჻჻
7 * Copyright 2023 Verax Systems, MetricsHub
8 * ჻჻჻჻჻჻
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation, either version 3 of the
12 * License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Lesser Public License for more details.
18 *
19 * You should have received a copy of the GNU General Lesser Public
20 * License along with this program. If not, see
21 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22 * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23 */
24
25 import org.metricshub.ipmi.core.coding.commands.CommandCodes;
26 import org.metricshub.ipmi.core.common.TypeConverter;
27
28 /**
29 * A wrapper class for IPMB LAN message
30 */
31 public class IpmiLanRequest extends IpmiLanMessage {
32
33 /** The network function is a 6-bit field (IPMI 2.0 section 5.1). */
34 private static final int MAX_NETWORK_FUNCTION_CODE = 0x3f;
35
36 /**
37 * Builds IpmiLanRequest addressed at LUN 0.
38 *
39 * @param networkFunction
40 * - command specific {@link NetworkFunction}
41 * @param commandCode
42 * - command specific {@link CommandCodes}
43 * @param requestData
44 * - command specific payload
45 * @param sequenceNumber
46 * - used to match request and response - must be in range [0-63]
47 */
48 public IpmiLanRequest(NetworkFunction networkFunction, byte commandCode, byte[] requestData, byte sequenceNumber) {
49 this(networkFunction, commandCode, requestData, sequenceNumber, TypeConverter.intToByte(0));
50 }
51
52 /**
53 * Builds IpmiLanRequest.
54 *
55 * @param networkFunction
56 * - command specific {@link NetworkFunction}
57 * @param commandCode
58 * - command specific {@link CommandCodes}
59 * @param requestData
60 * - command specific payload
61 * @param sequenceNumber
62 * - used to match request and response - must be in range [0-63]
63 * @param lun
64 * - target Logical Unit Number. Must be in range [0-3].
65 */
66 public IpmiLanRequest(NetworkFunction networkFunction, byte commandCode, byte[] requestData, byte sequenceNumber,
67 byte lun) {
68 this(networkFunction.getCode(), commandCode, requestData, sequenceNumber, lun);
69 }
70
71 /**
72 * Builds IpmiLanRequest addressed at LUN 0, under a network function given by its code, which may be one
73 * {@link NetworkFunction} does not list: Transport (0Ch), Group Extension (2Ch: DCMI, PICMG), OEM/Group (2Eh),
74 * controller-specific OEM (30h-3Eh), IPMI 2.0 table 5-1.
75 *
76 * @param networkFunctionCode
77 * - the network function code of the request, 00h to 3Fh
78 * @param commandCode
79 * - the command code
80 * @param requestData
81 * - command specific payload, null for none
82 * @param sequenceNumber
83 * - used to match request and response - must be in range [0-63]
84 * @throws IllegalArgumentException when the code does not fit in 6 bits
85 */
86 public IpmiLanRequest(int networkFunctionCode, byte commandCode, byte[] requestData, byte sequenceNumber) {
87 this(networkFunctionCode, commandCode, requestData, sequenceNumber, TypeConverter.intToByte(0));
88 }
89
90 private IpmiLanRequest(int networkFunctionCode, byte commandCode, byte[] requestData, byte sequenceNumber, byte lun) {
91 if (networkFunctionCode < 0 || networkFunctionCode > MAX_NETWORK_FUNCTION_CODE) {
92 throw new IllegalArgumentException("Invalid network function code: " + networkFunctionCode);
93 }
94 if (lun < 0 || lun > 3) {
95 throw new IllegalArgumentException("Invalid LUN");
96 }
97 setResponderAddress(IpmiLanConstants.BMC_ADDRESS);
98 setNetworkFunctionCode(TypeConverter.intToByte(networkFunctionCode));
99 setResponderLogicalUnitNumber(TypeConverter.intToByte(lun));
100 setRequesterAddress(IpmiLanConstants.REMOTE_CONSOLE_ADDRESS);
101 setRequesterLogicalUnitNumber(TypeConverter.intToByte(0));
102 setSequenceNumber(sequenceNumber);
103 setData(requestData);
104 setCommand(commandCode);
105 }
106
107 @Override
108 public int getPayloadLength() {
109 int length = 7;
110
111 if (getData() != null) {
112 length += getData().length;
113 }
114 return length;
115 }
116
117 @Override
118 public byte[] getPayloadData() {
119 byte[] message = new byte[getPayloadLength()];
120
121 message[0] = getResponderAddress();
122 message[1] = TypeConverter.intToByte((getNetworkFunctionCode() << 2) | getResponderLogicalUnitNumber());
123 message[2] = getChecksum1(message);
124 message[3] = getRequesterAddress();
125 message[4] = TypeConverter.intToByte(((getSequenceNumber() & 0x3f) << 2) | getRequesterLogicalUnitNumber()); // rqSeq/rqLUN
126 // (IPMI
127 // 2.0
128 // figure
129 // 13-4)
130 message[5] = getCommand();
131
132 if (getData() != null) {
133 System.arraycopy(getData(), 0, message, 6, getData().length);
134 }
135
136 message[message.length - 1] = getChecksum2(message);
137
138 return message;
139 }
140
141 }