blob: 690685196561939a17b3447aeed120900aba1e5b [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
Vivekanand Veeracholan55b1a712021-02-18 12:06:37 -0800320 EXPECT_CALL(pciMock, pci_device_enable(Eq(&dev))).Times(1);
321
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700322 if (deviceExpectations)
323 param->expectSetup(pciMock, dev);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700324}
325
326/* Test finding device and mapping memory region */
327TEST_P(PciSetupTest, Success)
328{
329 PciAccessMock pciMock;
330 struct pci_device dev;
331 std::vector<std::uint8_t> region(mockRegionSize);
332
333 expectSetup(pciMock, dev, GetParam(), region.data());
334
335 GetParam()->getBridge(&pciMock);
336}
337
338INSTANTIATE_TEST_SUITE_P(Default, PciSetupTest,
339 ::testing::Values(&nuvotonDevice, &aspeedDevice),
340 [](const testing::TestParamInfo<Device*>& info) {
341 return info.param->getName();
342 });
343
344TEST(NuvotonWriteTest, TooLarge)
345{
346 PciAccessMock pciMock;
347 struct pci_device dev;
348 std::vector<std::uint8_t> region(mockRegionSize);
349 std::vector<std::uint8_t> data(0x4001);
350
351 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
352
353 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
354 EXPECT_THROW(bridge->write(stdplus::span<std::uint8_t>(data)),
355 ToolException);
356}
357
358TEST(NuvotonWriteTest, Success)
359{
360 PciAccessMock pciMock;
361 struct pci_device dev;
362 std::vector<std::uint8_t> region(mockRegionSize);
363 std::vector<std::uint8_t> data(0x4000);
364
365 std::generate(data.begin(), data.end(), std::rand);
366
367 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
368
369 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
370 bridge->write(stdplus::span<std::uint8_t>(data));
371
372 EXPECT_THAT(stdplus::span<uint8_t>(&region[0], data.size()),
373 SpanEq(stdplus::span<uint8_t>(data)));
374}
375
376TEST(NuvotonConfigureTest, Success)
377{
378 PciAccessMock pciMock;
379 struct pci_device dev;
380 std::vector<std::uint8_t> region(mockRegionSize);
381 ipmi_flash::PciConfigResponse config{0x123bea51};
382
383 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
384
385 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
386 bridge->configure(config);
387
388 /* No effect from calling configure(), so the whole region should be 0 */
389 EXPECT_THAT(region, Each(0));
390}
391
392TEST(NuvotonDataLengthTest, Success)
393{
394 PciAccessMock pciMock;
395 struct pci_device dev;
396 std::vector<std::uint8_t> region(mockRegionSize);
397
398 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
399
400 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
401 EXPECT_EQ(bridge->getDataLength(), 0x4000);
402}
403
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700404/* Make sure config register is left alone if the bridge is already enabled */
405TEST(NuvotonBridgeTest, AlreadyEnabledSuccess)
406{
407 PciAccessMock pciMock;
408 struct pci_device dev;
409 std::vector<std::uint8_t> region(mockRegionSize);
410
411 constexpr std::uint8_t defaultVal = 0x40;
412
413 /* Only set standard expectations; not those from nuvotonDevice */
414 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
415
416 {
417 InSequence in;
418
419 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
420 NuvotonDevice::config))
421 .WillOnce(DoAll(
422 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
423 Return(0)));
424
425 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
426 NuvotonDevice::config))
427 .WillOnce(DoAll(
428 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
429 Return(0)));
430 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal,
431 NuvotonDevice::config))
432 .WillOnce(Return(0));
433 }
434
435 nuvotonDevice.getBridge(&pciMock);
436}
437
438/* Read fails when attempting to setup the bridge */
439TEST(NuvotonBridgeTest, ReadSetupFail)
440{
441 PciAccessMock pciMock;
442 struct pci_device dev;
443 std::vector<std::uint8_t> region(mockRegionSize);
444
445 /* Only set standard expectations; not those from nuvotonDevice */
446 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
447
448 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
449 NuvotonDevice::config))
450 .WillOnce(Return(EFAULT));
451
452 EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error);
453}
454
455/* Write fails when attempting to setup the bridge */
456TEST(NuvotonBridgeTest, WriteSetupFail)
457{
458 PciAccessMock pciMock;
459 struct pci_device dev;
460 std::vector<std::uint8_t> region(mockRegionSize);
461
462 constexpr std::uint8_t defaultVal = 0x40;
463
464 /* Only set standard expectations; not those from nuvotonDevice */
465 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
466
467 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
468 NuvotonDevice::config))
469 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
470 EXPECT_CALL(pciMock,
471 pci_device_cfg_write_u8(
472 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
473 NuvotonDevice::config))
474 .WillOnce(Return(EFAULT));
475
476 EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error);
477}
478
479/* Read fails when attempting to disable the bridge */
480TEST(NuvotonBridgeTest, ReadDisableFail)
481{
482 PciAccessMock pciMock;
483 struct pci_device dev;
484 std::vector<std::uint8_t> region(mockRegionSize);
485
486 constexpr std::uint8_t defaultVal = 0x40;
487
488 /* Only set standard expectations; not those from nuvotonDevice */
489 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
490
491 {
492 InSequence in;
493
494 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
495 NuvotonDevice::config))
496 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
497 EXPECT_CALL(pciMock,
498 pci_device_cfg_write_u8(
499 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
500 NuvotonDevice::config))
501 .WillOnce(Return(0));
502
503 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
504 NuvotonDevice::config))
505 .WillOnce(Return(EFAULT));
506 }
507
508 nuvotonDevice.getBridge(&pciMock);
509}
510
511/* Write fails when attempting to disable the bridge */
512TEST(NuvotonBridgeTest, WriteDisableFail)
513{
514 PciAccessMock pciMock;
515 struct pci_device dev;
516 std::vector<std::uint8_t> region(mockRegionSize);
517
518 constexpr std::uint8_t defaultVal = 0x40;
519
520 /* Only set standard expectations; not those from nuvotonDevice */
521 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
522
523 {
524 InSequence in;
525
526 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
527 NuvotonDevice::config))
528 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
529 EXPECT_CALL(pciMock,
530 pci_device_cfg_write_u8(
531 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
532 NuvotonDevice::config))
533 .WillOnce(Return(0));
534
535 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
536 NuvotonDevice::config))
537 .WillOnce(DoAll(
538 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
539 Return(0)));
540 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal,
541 NuvotonDevice::config))
542 .WillOnce(Return(EFAULT));
543 }
544
545 nuvotonDevice.getBridge(&pciMock);
546}
547
548/* Make sure the bridge gets enabled when needed */
549TEST(NuvotonBridgeTest, NotEnabledSuccess)
550{
551 PciAccessMock pciMock;
552 struct pci_device dev;
553 std::vector<std::uint8_t> region(mockRegionSize);
554
555 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
556 nuvotonDevice.getBridge(&pciMock);
557}
558
Willy Tu8a9de242020-10-30 11:00:21 -0700559/* Make sure it skips the disable bridge call when skipBridgeDisable is true */
560TEST(NuvotonBridgeTest, SkipDisable)
561{
562 PciAccessMock pciMock;
563 struct pci_device dev;
564 std::vector<std::uint8_t> region(mockRegionSize);
565
566 constexpr std::uint8_t defaultVal = 0x40;
567
568 /* Only set standard expectations; not those from nuvotonDevice */
569 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
570
571 {
572 InSequence in;
573
574 /* Only expect call for enableBridge() */
575 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
576 NuvotonDevice::config))
577 .WillOnce(DoAll(
578 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
579 Return(0)));
580 }
581
582 /* Setting skipBridgeDisable to true */
583 nuvotonDevice.getBridge(&pciMock, true);
584}
585
Benjamin Faire5aafa52020-06-05 21:04:24 -0700586TEST(AspeedWriteTest, TooLarge)
587{
588 PciAccessMock pciMock;
589 struct pci_device dev;
590 std::vector<std::uint8_t> region(mockRegionSize);
591 std::vector<std::uint8_t> data(0x10001);
592
593 expectSetup(pciMock, dev, &aspeedDevice, region.data());
594
595 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
596 EXPECT_THROW(bridge->write(stdplus::span<std::uint8_t>(data)),
597 ToolException);
598}
599
600TEST(AspeedWriteTest, Success)
601{
602 PciAccessMock pciMock;
603 struct pci_device dev;
604 std::vector<std::uint8_t> region(mockRegionSize);
605 std::vector<std::uint8_t> data(0x10000);
606
607 std::generate(data.begin(), data.end(), std::rand);
608
609 expectSetup(pciMock, dev, &aspeedDevice, region.data());
610
611 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
612 bridge->write(stdplus::span<std::uint8_t>(data));
613
614 EXPECT_THAT(stdplus::span<uint8_t>(&region[0x10000], data.size()),
615 SpanEq(stdplus::span<uint8_t>(data)));
616}
617
618TEST(AspeedConfigureTest, Success)
619{
620 PciAccessMock pciMock;
621 struct pci_device dev;
622 std::vector<std::uint8_t> region(mockRegionSize);
623 ipmi_flash::PciConfigResponse config{0x123bea51};
624
625 expectSetup(pciMock, dev, &aspeedDevice, region.data());
626
627 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
628 bridge->configure(config);
629
630 auto configSpan = stdplus::raw::asSpan<uint8_t>(config);
631 EXPECT_THAT(
632 stdplus::span<uint8_t>(&region[AspeedDevice::bridge], sizeof(config)),
633 SpanEq(configSpan));
634}
635
636TEST(AspeedDataLengthTest, Success)
637{
638 PciAccessMock pciMock;
639 struct pci_device dev;
640 std::vector<std::uint8_t> region(mockRegionSize);
641
642 expectSetup(pciMock, dev, &aspeedDevice, region.data());
643
644 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
645 EXPECT_EQ(bridge->getDataLength(), 0x10000);
646}
647
648/* Make sure config region is left alone if the bridge is already enabled */
649TEST(AspeedBridgeTest, AlreadyEnabledSuccess)
650{
651 PciAccessMock pciMock;
652 struct pci_device dev;
653 std::vector<std::uint8_t> region(mockRegionSize);
654
655 constexpr std::uint8_t defaultVal = 0x42;
656
657 region[AspeedDevice::config] = defaultVal | AspeedDevice::bridgeEnabled;
658
659 expectSetup(pciMock, dev, &aspeedDevice, region.data());
660
661 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
662
663 {
664 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
665 enabledRegion[AspeedDevice::config] =
666 defaultVal | AspeedDevice::bridgeEnabled;
667 EXPECT_THAT(region, ContainerEq(enabledRegion));
668 }
669
670 bridge.reset();
671
672 {
673 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
674 disabledRegion[AspeedDevice::config] = defaultVal;
675 EXPECT_THAT(region, ContainerEq(disabledRegion));
676 }
677}
678
Willy Tu8a9de242020-10-30 11:00:21 -0700679/* Make sure the config region remains the same even after cleanup if
680 * skipBridgeDisable is true */
681TEST(AspeedBridgeTest, SkipDisable)
682{
683 PciAccessMock pciMock;
684 struct pci_device dev;
685 std::vector<std::uint8_t> region(mockRegionSize);
686
687 constexpr std::uint8_t defaultVal = 0x42;
688
689 region[AspeedDevice::config] = defaultVal | AspeedDevice::bridgeEnabled;
690
691 expectSetup(pciMock, dev, &aspeedDevice, region.data());
692
693 /* Setting skipBridgeDisable to true */
694 std::unique_ptr<PciBridgeIntf> bridge =
695 aspeedDevice.getBridge(&pciMock, true);
696
697 {
698 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
699 enabledRegion[AspeedDevice::config] =
700 defaultVal | AspeedDevice::bridgeEnabled;
701 EXPECT_THAT(region, ContainerEq(enabledRegion));
702 }
703
704 bridge.reset();
705
706 {
707 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
708 disabledRegion[AspeedDevice::config] =
709 defaultVal | AspeedDevice::bridgeEnabled;
710 EXPECT_THAT(region, ContainerEq(disabledRegion));
711 }
712}
713
Benjamin Faire5aafa52020-06-05 21:04:24 -0700714/* Make sure the bridge gets enabled when needed */
715TEST(AspeedBridgeTest, NotEnabledSuccess)
716{
717 PciAccessMock pciMock;
718 struct pci_device dev;
719 std::vector<std::uint8_t> region(mockRegionSize);
720
721 constexpr std::uint8_t defaultVal = 0x42;
722
723 region[AspeedDevice::config] = defaultVal;
724
725 expectSetup(pciMock, dev, &aspeedDevice, region.data());
726
727 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
728
729 {
730 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
731 enabledRegion[AspeedDevice::config] =
732 defaultVal | AspeedDevice::bridgeEnabled;
733 EXPECT_THAT(region, ContainerEq(enabledRegion));
734 }
735
736 bridge.reset();
737
738 {
739 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
740 disabledRegion[AspeedDevice::config] = defaultVal;
741 EXPECT_THAT(region, ContainerEq(disabledRegion));
742 }
Benjamin Fair20a18092020-06-08 11:12:21 -0700743}
744
745} // namespace
746} // namespace host_tool