blob: 4c4f76ae0202655b8c1a6eff526eb36a7d6488f0 [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:
69 virtual const struct pci_id_match* getMatch() const = 0;
70 virtual struct pci_device getDevice() const = 0;
Benjamin Fairc1a30c02020-06-09 11:46:34 -070071 virtual void expectSetup(PciAccessMock& pciMock,
72 const struct pci_device& dev) const {};
Benjamin Faire5aafa52020-06-05 21:04:24 -070073 virtual std::unique_ptr<PciBridgeIntf> getBridge(PciAccess* pci) const = 0;
74 virtual std::string getName() const = 0;
75};
76
77class NuvotonDevice : public Device
78{
79 public:
80 const struct pci_id_match* getMatch() const override
81 {
82 return &match;
83 }
84
85 struct pci_device getDevice() const override
86 {
87 struct pci_device dev;
88
89 dev.vendor_id = match.vendor_id;
90 dev.device_id = match.device_id;
91
92 dev.regions[0].is_IO = false;
93 dev.regions[0].base_addr = mockBaseAddr;
94 dev.regions[0].size = mockRegionSize;
95
96 return dev;
97 }
98
Benjamin Fairc1a30c02020-06-09 11:46:34 -070099 void expectSetup(PciAccessMock& pciMock,
100 const struct pci_device& dev) const override
101 {
102 static constexpr std::uint8_t defaultVal = 0x40;
103
104 InSequence in;
105
106 EXPECT_CALL(pciMock,
107 pci_device_cfg_read_u8(Eq(&dev), NotNull(), config))
108 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
109 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(
110 Eq(&dev), defaultVal | bridgeEnabled, config))
111 .WillOnce(Return(0));
112
113 EXPECT_CALL(pciMock,
114 pci_device_cfg_read_u8(Eq(&dev), NotNull(), config))
115 .WillOnce(
116 DoAll(SetArgPointee<1>(defaultVal | bridgeEnabled), Return(0)));
117 EXPECT_CALL(pciMock,
118 pci_device_cfg_write_u8(Eq(&dev), defaultVal, config))
119 .WillOnce(Return(0));
120 }
121
Benjamin Faire5aafa52020-06-05 21:04:24 -0700122 std::unique_ptr<PciBridgeIntf> getBridge(PciAccess* pci) const override
123 {
124 return std::make_unique<NuvotonPciBridge>(pci);
125 }
126
127 std::string getName() const override
128 {
129 return "Nuvoton"s;
130 }
131
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700132 /* Offset to the config register */
133 static constexpr int config = 0x04;
134 /* Second bit determines whether bridge is enabled */
135 static constexpr std::uint8_t bridgeEnabled = 0x02;
136
Benjamin Faire5aafa52020-06-05 21:04:24 -0700137 private:
138 static constexpr struct pci_id_match match
139 {
140 0x1050, 0x0750, PCI_MATCH_ANY, PCI_MATCH_ANY
141 };
142};
143
144class AspeedDevice : public Device
145{
146 public:
147 const struct pci_id_match* getMatch() const override
148 {
149 return &match;
150 }
151
152 struct pci_device getDevice() const override
153 {
154 struct pci_device dev;
155
156 dev.vendor_id = match.vendor_id;
157 dev.device_id = match.device_id;
158
159 dev.regions[1].is_IO = false;
160 dev.regions[1].base_addr = mockBaseAddr;
161 dev.regions[1].size = mockRegionSize;
162
163 return dev;
164 }
165
166 std::unique_ptr<PciBridgeIntf> getBridge(PciAccess* pci) const override
167 {
168 return std::make_unique<AspeedPciBridge>(pci);
169 }
170
171 std::string getName() const override
172 {
173 return "Aspeed"s;
174 }
175
176 /* Offset to the config region */
177 static constexpr int config = 0x0f000;
178 /* Lower bit determines whether bridge is enabled */
179 static constexpr std::uint8_t bridgeEnabled = 0x01;
180 /* Offset to the MMIO address configuration */
181 static constexpr int bridge = 0x0f004;
182
183 private:
184 static constexpr struct pci_id_match match
185 {
186 0x1a03, 0x2000, PCI_MATCH_ANY, PCI_MATCH_ANY
187 };
188};
189
190NuvotonDevice nuvotonDevice;
191AspeedDevice aspeedDevice;
192
193class PciSetupTest : public testing::TestWithParam<Device*>
194{};
195
196/* Handle device not found */
197TEST_P(PciSetupTest, NotFound)
Benjamin Fair20a18092020-06-08 11:12:21 -0700198{
199 PciAccessMock pciMock;
200
Benjamin Faire5aafa52020-06-05 21:04:24 -0700201 InSequence in;
202
203 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
204 PciIdMatch(GetParam()->getMatch())))
205 .WillOnce(Return(mockIter));
206 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
207 .WillOnce(Return(nullptr));
208 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
209
210 EXPECT_THROW(GetParam()->getBridge(&pciMock), NotFoundException);
211}
212
213/* Test finding device but probe fails */
214TEST_P(PciSetupTest, ProbeFail)
215{
216 PciAccessMock pciMock;
217 struct pci_device dev;
218
219 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
220 PciIdMatch(GetParam()->getMatch())))
221 .WillOnce(Return(mockIter));
222 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
223 .WillOnce(Return(&dev))
224 .WillRepeatedly(Return(nullptr));
225
226 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev))).WillOnce(Return(EFAULT));
227
228 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
229
230 EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
231}
232
233/* Test finding device but mapping fails */
234TEST_P(PciSetupTest, MapFail)
235{
236 PciAccessMock pciMock;
237 struct pci_device dev;
238
239 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
240 PciIdMatch(GetParam()->getMatch())))
241 .WillOnce(Return(mockIter));
242 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
243 .WillOnce(Return(&dev))
244 .WillRepeatedly(Return(nullptr));
245
246 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
247 .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
248
249 EXPECT_CALL(pciMock,
250 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
251 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
252 .WillOnce(Return(EFAULT));
253
254 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
255
256 EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
257}
258
259/* Test finding device but unmapping fails */
260TEST_P(PciSetupTest, UnmapFail)
261{
262 PciAccessMock pciMock;
263 struct pci_device dev;
264 std::vector<std::uint8_t> region(mockRegionSize);
265
266 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
267 PciIdMatch(GetParam()->getMatch())))
268 .WillOnce(Return(mockIter));
269 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
270 .WillOnce(Return(&dev))
271 .WillRepeatedly(Return(nullptr));
272
273 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
274 .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
275
276 EXPECT_CALL(pciMock,
277 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
278 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
279 .WillOnce(DoAll(SetArgPointee<4>(region.data()), Return(0)));
280
281 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
282 EXPECT_CALL(pciMock, pci_device_unmap_range(Eq(&dev), Eq(region.data()),
283 mockRegionSize))
284 .WillOnce(Return(EFAULT));
285
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700286 GetParam()->expectSetup(pciMock, dev);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700287 // This will print an error but not throw
288 GetParam()->getBridge(&pciMock);
289}
290
291/* Create expectations on pciMock for finding device and mapping memory region
292 */
293void expectSetup(PciAccessMock& pciMock, struct pci_device& dev, Device* param,
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700294 std::uint8_t* region, bool deviceExpectations = true)
Benjamin Faire5aafa52020-06-05 21:04:24 -0700295{
296 EXPECT_CALL(pciMock,
297 pci_id_match_iterator_create(PciIdMatch(param->getMatch())))
298 .WillOnce(Return(mockIter));
299 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
300 .WillOnce(Return(&dev))
301 .WillRepeatedly(Return(nullptr));
302
303 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
304 .WillOnce(DoAll(Assign(&dev, param->getDevice()), Return(0)));
305
306 EXPECT_CALL(pciMock,
307 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
308 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
309 .WillOnce(DoAll(SetArgPointee<4>(region), Return(0)));
310
311 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
312 EXPECT_CALL(pciMock,
313 pci_device_unmap_range(Eq(&dev), Eq(region), mockRegionSize))
314 .WillOnce(Return(0));
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700315
316 if (deviceExpectations)
317 param->expectSetup(pciMock, dev);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700318}
319
320/* Test finding device and mapping memory region */
321TEST_P(PciSetupTest, Success)
322{
323 PciAccessMock pciMock;
324 struct pci_device dev;
325 std::vector<std::uint8_t> region(mockRegionSize);
326
327 expectSetup(pciMock, dev, GetParam(), region.data());
328
329 GetParam()->getBridge(&pciMock);
330}
331
332INSTANTIATE_TEST_SUITE_P(Default, PciSetupTest,
333 ::testing::Values(&nuvotonDevice, &aspeedDevice),
334 [](const testing::TestParamInfo<Device*>& info) {
335 return info.param->getName();
336 });
337
338TEST(NuvotonWriteTest, TooLarge)
339{
340 PciAccessMock pciMock;
341 struct pci_device dev;
342 std::vector<std::uint8_t> region(mockRegionSize);
343 std::vector<std::uint8_t> data(0x4001);
344
345 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
346
347 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
348 EXPECT_THROW(bridge->write(stdplus::span<std::uint8_t>(data)),
349 ToolException);
350}
351
352TEST(NuvotonWriteTest, Success)
353{
354 PciAccessMock pciMock;
355 struct pci_device dev;
356 std::vector<std::uint8_t> region(mockRegionSize);
357 std::vector<std::uint8_t> data(0x4000);
358
359 std::generate(data.begin(), data.end(), std::rand);
360
361 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
362
363 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
364 bridge->write(stdplus::span<std::uint8_t>(data));
365
366 EXPECT_THAT(stdplus::span<uint8_t>(&region[0], data.size()),
367 SpanEq(stdplus::span<uint8_t>(data)));
368}
369
370TEST(NuvotonConfigureTest, Success)
371{
372 PciAccessMock pciMock;
373 struct pci_device dev;
374 std::vector<std::uint8_t> region(mockRegionSize);
375 ipmi_flash::PciConfigResponse config{0x123bea51};
376
377 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
378
379 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
380 bridge->configure(config);
381
382 /* No effect from calling configure(), so the whole region should be 0 */
383 EXPECT_THAT(region, Each(0));
384}
385
386TEST(NuvotonDataLengthTest, Success)
387{
388 PciAccessMock pciMock;
389 struct pci_device dev;
390 std::vector<std::uint8_t> region(mockRegionSize);
391
392 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
393
394 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
395 EXPECT_EQ(bridge->getDataLength(), 0x4000);
396}
397
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700398/* Make sure config register is left alone if the bridge is already enabled */
399TEST(NuvotonBridgeTest, AlreadyEnabledSuccess)
400{
401 PciAccessMock pciMock;
402 struct pci_device dev;
403 std::vector<std::uint8_t> region(mockRegionSize);
404
405 constexpr std::uint8_t defaultVal = 0x40;
406
407 /* Only set standard expectations; not those from nuvotonDevice */
408 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
409
410 {
411 InSequence in;
412
413 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
414 NuvotonDevice::config))
415 .WillOnce(DoAll(
416 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
417 Return(0)));
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 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal,
425 NuvotonDevice::config))
426 .WillOnce(Return(0));
427 }
428
429 nuvotonDevice.getBridge(&pciMock);
430}
431
432/* Read fails when attempting to setup the bridge */
433TEST(NuvotonBridgeTest, ReadSetupFail)
434{
435 PciAccessMock pciMock;
436 struct pci_device dev;
437 std::vector<std::uint8_t> region(mockRegionSize);
438
439 /* Only set standard expectations; not those from nuvotonDevice */
440 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
441
442 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
443 NuvotonDevice::config))
444 .WillOnce(Return(EFAULT));
445
446 EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error);
447}
448
449/* Write fails when attempting to setup the bridge */
450TEST(NuvotonBridgeTest, WriteSetupFail)
451{
452 PciAccessMock pciMock;
453 struct pci_device dev;
454 std::vector<std::uint8_t> region(mockRegionSize);
455
456 constexpr std::uint8_t defaultVal = 0x40;
457
458 /* Only set standard expectations; not those from nuvotonDevice */
459 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
460
461 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
462 NuvotonDevice::config))
463 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
464 EXPECT_CALL(pciMock,
465 pci_device_cfg_write_u8(
466 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
467 NuvotonDevice::config))
468 .WillOnce(Return(EFAULT));
469
470 EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error);
471}
472
473/* Read fails when attempting to disable the bridge */
474TEST(NuvotonBridgeTest, ReadDisableFail)
475{
476 PciAccessMock pciMock;
477 struct pci_device dev;
478 std::vector<std::uint8_t> region(mockRegionSize);
479
480 constexpr std::uint8_t defaultVal = 0x40;
481
482 /* Only set standard expectations; not those from nuvotonDevice */
483 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
484
485 {
486 InSequence in;
487
488 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
489 NuvotonDevice::config))
490 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
491 EXPECT_CALL(pciMock,
492 pci_device_cfg_write_u8(
493 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
494 NuvotonDevice::config))
495 .WillOnce(Return(0));
496
497 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
498 NuvotonDevice::config))
499 .WillOnce(Return(EFAULT));
500 }
501
502 nuvotonDevice.getBridge(&pciMock);
503}
504
505/* Write fails when attempting to disable the bridge */
506TEST(NuvotonBridgeTest, WriteDisableFail)
507{
508 PciAccessMock pciMock;
509 struct pci_device dev;
510 std::vector<std::uint8_t> region(mockRegionSize);
511
512 constexpr std::uint8_t defaultVal = 0x40;
513
514 /* Only set standard expectations; not those from nuvotonDevice */
515 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
516
517 {
518 InSequence in;
519
520 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
521 NuvotonDevice::config))
522 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
523 EXPECT_CALL(pciMock,
524 pci_device_cfg_write_u8(
525 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
526 NuvotonDevice::config))
527 .WillOnce(Return(0));
528
529 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
530 NuvotonDevice::config))
531 .WillOnce(DoAll(
532 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
533 Return(0)));
534 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal,
535 NuvotonDevice::config))
536 .WillOnce(Return(EFAULT));
537 }
538
539 nuvotonDevice.getBridge(&pciMock);
540}
541
542/* Make sure the bridge gets enabled when needed */
543TEST(NuvotonBridgeTest, NotEnabledSuccess)
544{
545 PciAccessMock pciMock;
546 struct pci_device dev;
547 std::vector<std::uint8_t> region(mockRegionSize);
548
549 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
550 nuvotonDevice.getBridge(&pciMock);
551}
552
Benjamin Faire5aafa52020-06-05 21:04:24 -0700553TEST(AspeedWriteTest, TooLarge)
554{
555 PciAccessMock pciMock;
556 struct pci_device dev;
557 std::vector<std::uint8_t> region(mockRegionSize);
558 std::vector<std::uint8_t> data(0x10001);
559
560 expectSetup(pciMock, dev, &aspeedDevice, region.data());
561
562 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
563 EXPECT_THROW(bridge->write(stdplus::span<std::uint8_t>(data)),
564 ToolException);
565}
566
567TEST(AspeedWriteTest, Success)
568{
569 PciAccessMock pciMock;
570 struct pci_device dev;
571 std::vector<std::uint8_t> region(mockRegionSize);
572 std::vector<std::uint8_t> data(0x10000);
573
574 std::generate(data.begin(), data.end(), std::rand);
575
576 expectSetup(pciMock, dev, &aspeedDevice, region.data());
577
578 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
579 bridge->write(stdplus::span<std::uint8_t>(data));
580
581 EXPECT_THAT(stdplus::span<uint8_t>(&region[0x10000], data.size()),
582 SpanEq(stdplus::span<uint8_t>(data)));
583}
584
585TEST(AspeedConfigureTest, Success)
586{
587 PciAccessMock pciMock;
588 struct pci_device dev;
589 std::vector<std::uint8_t> region(mockRegionSize);
590 ipmi_flash::PciConfigResponse config{0x123bea51};
591
592 expectSetup(pciMock, dev, &aspeedDevice, region.data());
593
594 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
595 bridge->configure(config);
596
597 auto configSpan = stdplus::raw::asSpan<uint8_t>(config);
598 EXPECT_THAT(
599 stdplus::span<uint8_t>(&region[AspeedDevice::bridge], sizeof(config)),
600 SpanEq(configSpan));
601}
602
603TEST(AspeedDataLengthTest, Success)
604{
605 PciAccessMock pciMock;
606 struct pci_device dev;
607 std::vector<std::uint8_t> region(mockRegionSize);
608
609 expectSetup(pciMock, dev, &aspeedDevice, region.data());
610
611 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
612 EXPECT_EQ(bridge->getDataLength(), 0x10000);
613}
614
615/* Make sure config region is left alone if the bridge is already enabled */
616TEST(AspeedBridgeTest, AlreadyEnabledSuccess)
617{
618 PciAccessMock pciMock;
619 struct pci_device dev;
620 std::vector<std::uint8_t> region(mockRegionSize);
621
622 constexpr std::uint8_t defaultVal = 0x42;
623
624 region[AspeedDevice::config] = defaultVal | AspeedDevice::bridgeEnabled;
625
626 expectSetup(pciMock, dev, &aspeedDevice, region.data());
627
628 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
629
630 {
631 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
632 enabledRegion[AspeedDevice::config] =
633 defaultVal | AspeedDevice::bridgeEnabled;
634 EXPECT_THAT(region, ContainerEq(enabledRegion));
635 }
636
637 bridge.reset();
638
639 {
640 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
641 disabledRegion[AspeedDevice::config] = defaultVal;
642 EXPECT_THAT(region, ContainerEq(disabledRegion));
643 }
644}
645
646/* Make sure the bridge gets enabled when needed */
647TEST(AspeedBridgeTest, NotEnabledSuccess)
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;
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 }
Benjamin Fair20a18092020-06-08 11:12:21 -0700675}
676
677} // namespace
678} // namespace host_tool