blob: 7f69db26c3e5c27c2d485f7f599cd780ae48326e [file] [log] [blame]
Benjamin Faire5aafa52020-06-05 21:04:24 -07001/*
2 * Copyright 2020 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Benjamin Fair20a18092020-06-08 11:12:21 -070017#include "internal_sys_mock.hpp"
Benjamin Faire5aafa52020-06-05 21:04:24 -070018#include "pci.hpp"
Benjamin Fair20a18092020-06-08 11:12:21 -070019#include "pciaccess_mock.hpp"
Benjamin Faire5aafa52020-06-05 21:04:24 -070020#include "tool_errors.hpp"
21
22#include <stdplus/raw.hpp>
23
24#include <algorithm>
25#include <cstdlib>
26#include <string>
27#include <vector>
Benjamin Fair20a18092020-06-08 11:12:21 -070028
29#include <gtest/gtest.h>
30
31namespace host_tool
32{
33namespace
34{
35
Benjamin Faire5aafa52020-06-05 21:04:24 -070036using namespace std::string_literals;
37
38using ::testing::Assign;
39using ::testing::ContainerEq;
40using ::testing::DoAll;
41using ::testing::Each;
42using ::testing::Eq;
43using ::testing::InSequence;
44using ::testing::NotNull;
45using ::testing::Return;
46using ::testing::SetArgPointee;
47
48// TODO: switch to ConainerEq for C++20
49MATCHER_P(SpanEq, s, "")
50{
51 return arg.size() == s.size() && !memcmp(arg.data(), s.data(), s.size());
52}
53
54MATCHER_P(PciIdMatch, m, "")
55{
56 return (arg->vendor_id == m->vendor_id && arg->device_id == m->device_id &&
57 arg->subvendor_id == m->subvendor_id &&
58 arg->subdevice_id == m->subdevice_id);
59}
60
61pci_device_iterator* mockIter = reinterpret_cast<pci_device_iterator*>(0x42);
62
63constexpr pciaddr_t mockBaseAddr = 0xdeadbeef;
64constexpr pciaddr_t mockRegionSize = 0x20000;
65
66class Device
67{
68 public:
Patrick Venturee261ca22020-09-28 12:47:39 -070069 virtual ~Device() = default;
Benjamin Faire5aafa52020-06-05 21:04:24 -070070 virtual const struct pci_id_match* getMatch() const = 0;
71 virtual struct pci_device getDevice() const = 0;
Benjamin Fairc1a30c02020-06-09 11:46:34 -070072 virtual void expectSetup(PciAccessMock& pciMock,
73 const struct pci_device& dev) const {};
Willy Tu8a9de242020-10-30 11:00:21 -070074 virtual std::unique_ptr<PciBridgeIntf>
75 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const = 0;
Benjamin Faire5aafa52020-06-05 21:04:24 -070076 virtual std::string getName() const = 0;
77};
78
79class NuvotonDevice : public Device
80{
81 public:
82 const struct pci_id_match* getMatch() const override
83 {
84 return &match;
85 }
86
87 struct pci_device getDevice() const override
88 {
89 struct pci_device dev;
90
91 dev.vendor_id = match.vendor_id;
92 dev.device_id = match.device_id;
93
94 dev.regions[0].is_IO = false;
95 dev.regions[0].base_addr = mockBaseAddr;
96 dev.regions[0].size = mockRegionSize;
97
98 return dev;
99 }
100
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700101 void expectSetup(PciAccessMock& pciMock,
102 const struct pci_device& dev) const override
103 {
104 static constexpr std::uint8_t defaultVal = 0x40;
105
106 InSequence in;
107
108 EXPECT_CALL(pciMock,
109 pci_device_cfg_read_u8(Eq(&dev), NotNull(), config))
110 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
111 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(
112 Eq(&dev), defaultVal | bridgeEnabled, config))
113 .WillOnce(Return(0));
114
115 EXPECT_CALL(pciMock,
116 pci_device_cfg_read_u8(Eq(&dev), NotNull(), config))
117 .WillOnce(
118 DoAll(SetArgPointee<1>(defaultVal | bridgeEnabled), Return(0)));
119 EXPECT_CALL(pciMock,
120 pci_device_cfg_write_u8(Eq(&dev), defaultVal, config))
121 .WillOnce(Return(0));
122 }
123
Willy Tu8a9de242020-10-30 11:00:21 -0700124 std::unique_ptr<PciBridgeIntf>
125 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const override
Benjamin Faire5aafa52020-06-05 21:04:24 -0700126 {
Willy Tu8a9de242020-10-30 11:00:21 -0700127 return std::make_unique<NuvotonPciBridge>(pci, skipBridgeDisable);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700128 }
129
130 std::string getName() const override
131 {
132 return "Nuvoton"s;
133 }
134
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700135 /* Offset to the config register */
136 static constexpr int config = 0x04;
137 /* Second bit determines whether bridge is enabled */
138 static constexpr std::uint8_t bridgeEnabled = 0x02;
139
Benjamin Faire5aafa52020-06-05 21:04:24 -0700140 private:
141 static constexpr struct pci_id_match match
142 {
143 0x1050, 0x0750, PCI_MATCH_ANY, PCI_MATCH_ANY
144 };
145};
146
147class AspeedDevice : public Device
148{
149 public:
150 const struct pci_id_match* getMatch() const override
151 {
152 return &match;
153 }
154
155 struct pci_device getDevice() const override
156 {
157 struct pci_device dev;
158
159 dev.vendor_id = match.vendor_id;
160 dev.device_id = match.device_id;
161
162 dev.regions[1].is_IO = false;
163 dev.regions[1].base_addr = mockBaseAddr;
164 dev.regions[1].size = mockRegionSize;
165
166 return dev;
167 }
168
Willy Tu8a9de242020-10-30 11:00:21 -0700169 std::unique_ptr<PciBridgeIntf>
170 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const override
Benjamin Faire5aafa52020-06-05 21:04:24 -0700171 {
Willy Tu8a9de242020-10-30 11:00:21 -0700172 return std::make_unique<AspeedPciBridge>(pci, skipBridgeDisable);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700173 }
174
175 std::string getName() const override
176 {
177 return "Aspeed"s;
178 }
179
180 /* Offset to the config region */
181 static constexpr int config = 0x0f000;
182 /* Lower bit determines whether bridge is enabled */
183 static constexpr std::uint8_t bridgeEnabled = 0x01;
184 /* Offset to the MMIO address configuration */
185 static constexpr int bridge = 0x0f004;
186
187 private:
188 static constexpr struct pci_id_match match
189 {
190 0x1a03, 0x2000, PCI_MATCH_ANY, PCI_MATCH_ANY
191 };
192};
193
194NuvotonDevice nuvotonDevice;
195AspeedDevice aspeedDevice;
196
197class PciSetupTest : public testing::TestWithParam<Device*>
198{};
199
200/* Handle device not found */
201TEST_P(PciSetupTest, NotFound)
Benjamin Fair20a18092020-06-08 11:12:21 -0700202{
203 PciAccessMock pciMock;
204
Benjamin Faire5aafa52020-06-05 21:04:24 -0700205 InSequence in;
206
207 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
208 PciIdMatch(GetParam()->getMatch())))
209 .WillOnce(Return(mockIter));
210 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
211 .WillOnce(Return(nullptr));
212 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
213
214 EXPECT_THROW(GetParam()->getBridge(&pciMock), NotFoundException);
215}
216
217/* Test finding device but probe fails */
218TEST_P(PciSetupTest, ProbeFail)
219{
220 PciAccessMock pciMock;
221 struct pci_device dev;
222
223 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
224 PciIdMatch(GetParam()->getMatch())))
225 .WillOnce(Return(mockIter));
226 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
227 .WillOnce(Return(&dev))
228 .WillRepeatedly(Return(nullptr));
229
230 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev))).WillOnce(Return(EFAULT));
231
232 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
233
234 EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
235}
236
237/* Test finding device but mapping fails */
238TEST_P(PciSetupTest, MapFail)
239{
240 PciAccessMock pciMock;
241 struct pci_device dev;
242
243 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
244 PciIdMatch(GetParam()->getMatch())))
245 .WillOnce(Return(mockIter));
246 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
247 .WillOnce(Return(&dev))
248 .WillRepeatedly(Return(nullptr));
249
250 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
251 .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
252
253 EXPECT_CALL(pciMock,
254 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
255 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
256 .WillOnce(Return(EFAULT));
257
258 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
259
260 EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
261}
262
263/* Test finding device but unmapping fails */
264TEST_P(PciSetupTest, UnmapFail)
265{
266 PciAccessMock pciMock;
267 struct pci_device dev;
268 std::vector<std::uint8_t> region(mockRegionSize);
269
270 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
271 PciIdMatch(GetParam()->getMatch())))
272 .WillOnce(Return(mockIter));
273 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
274 .WillOnce(Return(&dev))
275 .WillRepeatedly(Return(nullptr));
276
277 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
278 .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
279
280 EXPECT_CALL(pciMock,
281 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
282 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
283 .WillOnce(DoAll(SetArgPointee<4>(region.data()), Return(0)));
284
285 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
286 EXPECT_CALL(pciMock, pci_device_unmap_range(Eq(&dev), Eq(region.data()),
287 mockRegionSize))
288 .WillOnce(Return(EFAULT));
289
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700290 GetParam()->expectSetup(pciMock, dev);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700291 // This will print an error but not throw
292 GetParam()->getBridge(&pciMock);
293}
294
295/* Create expectations on pciMock for finding device and mapping memory region
296 */
297void expectSetup(PciAccessMock& pciMock, struct pci_device& dev, Device* param,
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700298 std::uint8_t* region, bool deviceExpectations = true)
Benjamin Faire5aafa52020-06-05 21:04:24 -0700299{
300 EXPECT_CALL(pciMock,
301 pci_id_match_iterator_create(PciIdMatch(param->getMatch())))
302 .WillOnce(Return(mockIter));
303 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
304 .WillOnce(Return(&dev))
305 .WillRepeatedly(Return(nullptr));
306
307 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
308 .WillOnce(DoAll(Assign(&dev, param->getDevice()), Return(0)));
309
310 EXPECT_CALL(pciMock,
311 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
312 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
313 .WillOnce(DoAll(SetArgPointee<4>(region), Return(0)));
314
315 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
316 EXPECT_CALL(pciMock,
317 pci_device_unmap_range(Eq(&dev), Eq(region), mockRegionSize))
318 .WillOnce(Return(0));
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700319
320 if (deviceExpectations)
321 param->expectSetup(pciMock, dev);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700322}
323
324/* Test finding device and mapping memory region */
325TEST_P(PciSetupTest, Success)
326{
327 PciAccessMock pciMock;
328 struct pci_device dev;
329 std::vector<std::uint8_t> region(mockRegionSize);
330
331 expectSetup(pciMock, dev, GetParam(), region.data());
332
333 GetParam()->getBridge(&pciMock);
334}
335
336INSTANTIATE_TEST_SUITE_P(Default, PciSetupTest,
337 ::testing::Values(&nuvotonDevice, &aspeedDevice),
338 [](const testing::TestParamInfo<Device*>& info) {
339 return info.param->getName();
340 });
341
342TEST(NuvotonWriteTest, TooLarge)
343{
344 PciAccessMock pciMock;
345 struct pci_device dev;
346 std::vector<std::uint8_t> region(mockRegionSize);
347 std::vector<std::uint8_t> data(0x4001);
348
349 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
350
351 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
352 EXPECT_THROW(bridge->write(stdplus::span<std::uint8_t>(data)),
353 ToolException);
354}
355
356TEST(NuvotonWriteTest, Success)
357{
358 PciAccessMock pciMock;
359 struct pci_device dev;
360 std::vector<std::uint8_t> region(mockRegionSize);
361 std::vector<std::uint8_t> data(0x4000);
362
363 std::generate(data.begin(), data.end(), std::rand);
364
365 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
366
367 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
368 bridge->write(stdplus::span<std::uint8_t>(data));
369
370 EXPECT_THAT(stdplus::span<uint8_t>(&region[0], data.size()),
371 SpanEq(stdplus::span<uint8_t>(data)));
372}
373
374TEST(NuvotonConfigureTest, Success)
375{
376 PciAccessMock pciMock;
377 struct pci_device dev;
378 std::vector<std::uint8_t> region(mockRegionSize);
379 ipmi_flash::PciConfigResponse config{0x123bea51};
380
381 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
382
383 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
384 bridge->configure(config);
385
386 /* No effect from calling configure(), so the whole region should be 0 */
387 EXPECT_THAT(region, Each(0));
388}
389
390TEST(NuvotonDataLengthTest, Success)
391{
392 PciAccessMock pciMock;
393 struct pci_device dev;
394 std::vector<std::uint8_t> region(mockRegionSize);
395
396 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
397
398 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
399 EXPECT_EQ(bridge->getDataLength(), 0x4000);
400}
401
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700402/* Make sure config register is left alone if the bridge is already enabled */
403TEST(NuvotonBridgeTest, AlreadyEnabledSuccess)
404{
405 PciAccessMock pciMock;
406 struct pci_device dev;
407 std::vector<std::uint8_t> region(mockRegionSize);
408
409 constexpr std::uint8_t defaultVal = 0x40;
410
411 /* Only set standard expectations; not those from nuvotonDevice */
412 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
413
414 {
415 InSequence in;
416
417 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
418 NuvotonDevice::config))
419 .WillOnce(DoAll(
420 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
421 Return(0)));
422
423 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
424 NuvotonDevice::config))
425 .WillOnce(DoAll(
426 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
427 Return(0)));
428 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal,
429 NuvotonDevice::config))
430 .WillOnce(Return(0));
431 }
432
433 nuvotonDevice.getBridge(&pciMock);
434}
435
436/* Read fails when attempting to setup the bridge */
437TEST(NuvotonBridgeTest, ReadSetupFail)
438{
439 PciAccessMock pciMock;
440 struct pci_device dev;
441 std::vector<std::uint8_t> region(mockRegionSize);
442
443 /* Only set standard expectations; not those from nuvotonDevice */
444 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
445
446 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
447 NuvotonDevice::config))
448 .WillOnce(Return(EFAULT));
449
450 EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error);
451}
452
453/* Write fails when attempting to setup the bridge */
454TEST(NuvotonBridgeTest, WriteSetupFail)
455{
456 PciAccessMock pciMock;
457 struct pci_device dev;
458 std::vector<std::uint8_t> region(mockRegionSize);
459
460 constexpr std::uint8_t defaultVal = 0x40;
461
462 /* Only set standard expectations; not those from nuvotonDevice */
463 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
464
465 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
466 NuvotonDevice::config))
467 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
468 EXPECT_CALL(pciMock,
469 pci_device_cfg_write_u8(
470 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
471 NuvotonDevice::config))
472 .WillOnce(Return(EFAULT));
473
474 EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error);
475}
476
477/* Read fails when attempting to disable the bridge */
478TEST(NuvotonBridgeTest, ReadDisableFail)
479{
480 PciAccessMock pciMock;
481 struct pci_device dev;
482 std::vector<std::uint8_t> region(mockRegionSize);
483
484 constexpr std::uint8_t defaultVal = 0x40;
485
486 /* Only set standard expectations; not those from nuvotonDevice */
487 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
488
489 {
490 InSequence in;
491
492 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
493 NuvotonDevice::config))
494 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
495 EXPECT_CALL(pciMock,
496 pci_device_cfg_write_u8(
497 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
498 NuvotonDevice::config))
499 .WillOnce(Return(0));
500
501 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
502 NuvotonDevice::config))
503 .WillOnce(Return(EFAULT));
504 }
505
506 nuvotonDevice.getBridge(&pciMock);
507}
508
509/* Write fails when attempting to disable the bridge */
510TEST(NuvotonBridgeTest, WriteDisableFail)
511{
512 PciAccessMock pciMock;
513 struct pci_device dev;
514 std::vector<std::uint8_t> region(mockRegionSize);
515
516 constexpr std::uint8_t defaultVal = 0x40;
517
518 /* Only set standard expectations; not those from nuvotonDevice */
519 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
520
521 {
522 InSequence in;
523
524 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
525 NuvotonDevice::config))
526 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
527 EXPECT_CALL(pciMock,
528 pci_device_cfg_write_u8(
529 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
530 NuvotonDevice::config))
531 .WillOnce(Return(0));
532
533 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
534 NuvotonDevice::config))
535 .WillOnce(DoAll(
536 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
537 Return(0)));
538 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal,
539 NuvotonDevice::config))
540 .WillOnce(Return(EFAULT));
541 }
542
543 nuvotonDevice.getBridge(&pciMock);
544}
545
546/* Make sure the bridge gets enabled when needed */
547TEST(NuvotonBridgeTest, NotEnabledSuccess)
548{
549 PciAccessMock pciMock;
550 struct pci_device dev;
551 std::vector<std::uint8_t> region(mockRegionSize);
552
553 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
554 nuvotonDevice.getBridge(&pciMock);
555}
556
Willy Tu8a9de242020-10-30 11:00:21 -0700557/* Make sure it skips the disable bridge call when skipBridgeDisable is true */
558TEST(NuvotonBridgeTest, SkipDisable)
559{
560 PciAccessMock pciMock;
561 struct pci_device dev;
562 std::vector<std::uint8_t> region(mockRegionSize);
563
564 constexpr std::uint8_t defaultVal = 0x40;
565
566 /* Only set standard expectations; not those from nuvotonDevice */
567 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
568
569 {
570 InSequence in;
571
572 /* Only expect call for enableBridge() */
573 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
574 NuvotonDevice::config))
575 .WillOnce(DoAll(
576 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
577 Return(0)));
578 }
579
580 /* Setting skipBridgeDisable to true */
581 nuvotonDevice.getBridge(&pciMock, true);
582}
583
Benjamin Faire5aafa52020-06-05 21:04:24 -0700584TEST(AspeedWriteTest, TooLarge)
585{
586 PciAccessMock pciMock;
587 struct pci_device dev;
588 std::vector<std::uint8_t> region(mockRegionSize);
589 std::vector<std::uint8_t> data(0x10001);
590
591 expectSetup(pciMock, dev, &aspeedDevice, region.data());
592
593 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
594 EXPECT_THROW(bridge->write(stdplus::span<std::uint8_t>(data)),
595 ToolException);
596}
597
598TEST(AspeedWriteTest, Success)
599{
600 PciAccessMock pciMock;
601 struct pci_device dev;
602 std::vector<std::uint8_t> region(mockRegionSize);
603 std::vector<std::uint8_t> data(0x10000);
604
605 std::generate(data.begin(), data.end(), std::rand);
606
607 expectSetup(pciMock, dev, &aspeedDevice, region.data());
608
609 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
610 bridge->write(stdplus::span<std::uint8_t>(data));
611
612 EXPECT_THAT(stdplus::span<uint8_t>(&region[0x10000], data.size()),
613 SpanEq(stdplus::span<uint8_t>(data)));
614}
615
616TEST(AspeedConfigureTest, Success)
617{
618 PciAccessMock pciMock;
619 struct pci_device dev;
620 std::vector<std::uint8_t> region(mockRegionSize);
621 ipmi_flash::PciConfigResponse config{0x123bea51};
622
623 expectSetup(pciMock, dev, &aspeedDevice, region.data());
624
625 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
626 bridge->configure(config);
627
628 auto configSpan = stdplus::raw::asSpan<uint8_t>(config);
629 EXPECT_THAT(
630 stdplus::span<uint8_t>(&region[AspeedDevice::bridge], sizeof(config)),
631 SpanEq(configSpan));
632}
633
634TEST(AspeedDataLengthTest, Success)
635{
636 PciAccessMock pciMock;
637 struct pci_device dev;
638 std::vector<std::uint8_t> region(mockRegionSize);
639
640 expectSetup(pciMock, dev, &aspeedDevice, region.data());
641
642 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
643 EXPECT_EQ(bridge->getDataLength(), 0x10000);
644}
645
646/* Make sure config region is left alone if the bridge is already enabled */
647TEST(AspeedBridgeTest, AlreadyEnabledSuccess)
648{
649 PciAccessMock pciMock;
650 struct pci_device dev;
651 std::vector<std::uint8_t> region(mockRegionSize);
652
653 constexpr std::uint8_t defaultVal = 0x42;
654
655 region[AspeedDevice::config] = defaultVal | AspeedDevice::bridgeEnabled;
656
657 expectSetup(pciMock, dev, &aspeedDevice, region.data());
658
659 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
660
661 {
662 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
663 enabledRegion[AspeedDevice::config] =
664 defaultVal | AspeedDevice::bridgeEnabled;
665 EXPECT_THAT(region, ContainerEq(enabledRegion));
666 }
667
668 bridge.reset();
669
670 {
671 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
672 disabledRegion[AspeedDevice::config] = defaultVal;
673 EXPECT_THAT(region, ContainerEq(disabledRegion));
674 }
675}
676
Willy Tu8a9de242020-10-30 11:00:21 -0700677/* Make sure the config region remains the same even after cleanup if
678 * skipBridgeDisable is true */
679TEST(AspeedBridgeTest, SkipDisable)
680{
681 PciAccessMock pciMock;
682 struct pci_device dev;
683 std::vector<std::uint8_t> region(mockRegionSize);
684
685 constexpr std::uint8_t defaultVal = 0x42;
686
687 region[AspeedDevice::config] = defaultVal | AspeedDevice::bridgeEnabled;
688
689 expectSetup(pciMock, dev, &aspeedDevice, region.data());
690
691 /* Setting skipBridgeDisable to true */
692 std::unique_ptr<PciBridgeIntf> bridge =
693 aspeedDevice.getBridge(&pciMock, true);
694
695 {
696 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
697 enabledRegion[AspeedDevice::config] =
698 defaultVal | AspeedDevice::bridgeEnabled;
699 EXPECT_THAT(region, ContainerEq(enabledRegion));
700 }
701
702 bridge.reset();
703
704 {
705 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
706 disabledRegion[AspeedDevice::config] =
707 defaultVal | AspeedDevice::bridgeEnabled;
708 EXPECT_THAT(region, ContainerEq(disabledRegion));
709 }
710}
711
Benjamin Faire5aafa52020-06-05 21:04:24 -0700712/* Make sure the bridge gets enabled when needed */
713TEST(AspeedBridgeTest, NotEnabledSuccess)
714{
715 PciAccessMock pciMock;
716 struct pci_device dev;
717 std::vector<std::uint8_t> region(mockRegionSize);
718
719 constexpr std::uint8_t defaultVal = 0x42;
720
721 region[AspeedDevice::config] = defaultVal;
722
723 expectSetup(pciMock, dev, &aspeedDevice, region.data());
724
725 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
726
727 {
728 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
729 enabledRegion[AspeedDevice::config] =
730 defaultVal | AspeedDevice::bridgeEnabled;
731 EXPECT_THAT(region, ContainerEq(enabledRegion));
732 }
733
734 bridge.reset();
735
736 {
737 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
738 disabledRegion[AspeedDevice::config] = defaultVal;
739 EXPECT_THAT(region, ContainerEq(disabledRegion));
740 }
Benjamin Fair20a18092020-06-08 11:12:21 -0700741}
742
743} // namespace
744} // namespace host_tool