1 /* 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 17 #include "internal_sys_mock.hpp" 18 #include "pci.hpp" 19 #include "pciaccess_mock.hpp" 20 #include "tool_errors.hpp" 21 22 #include <stdplus/raw.hpp> 23 24 #include <algorithm> 25 #include <cstdlib> 26 #include <string> 27 #include <vector> 28 29 #include <gtest/gtest.h> 30 31 namespace host_tool 32 { 33 namespace 34 { 35 36 using namespace std::string_literals; 37 38 using ::testing::Assign; 39 using ::testing::ContainerEq; 40 using ::testing::DoAll; 41 using ::testing::Each; 42 using ::testing::Eq; 43 using ::testing::InSequence; 44 using ::testing::NotNull; 45 using ::testing::Return; 46 using ::testing::SetArgPointee; 47 48 // TODO: switch to ConainerEq for C++20 49 MATCHER_P(SpanEq, s, "") 50 { 51 return arg.size() == s.size() && !memcmp(arg.data(), s.data(), s.size()); 52 } 53 54 MATCHER_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 61 pci_device_iterator* mockIter = reinterpret_cast<pci_device_iterator*>(0x42); 62 63 constexpr pciaddr_t mockBaseAddr = 0xdeadbeef; 64 constexpr pciaddr_t mockRegionSize = 0x20000; 65 66 class Device 67 { 68 public: 69 virtual ~Device() = default; 70 virtual const struct pci_id_match* getMatch() const = 0; 71 virtual struct pci_device getDevice() const = 0; 72 virtual void expectSetup(PciAccessMock& pciMock, 73 const struct pci_device& dev) const {}; 74 virtual std::unique_ptr<PciBridgeIntf> 75 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const = 0; 76 virtual std::string getName() const = 0; 77 }; 78 79 class 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 101 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 124 std::unique_ptr<PciBridgeIntf> 125 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const override 126 { 127 return std::make_unique<NuvotonPciBridge>(pci, skipBridgeDisable); 128 } 129 130 std::string getName() const override 131 { 132 return "Nuvoton"s; 133 } 134 135 /* 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 140 private: 141 static constexpr struct pci_id_match match 142 { 143 0x1050, 0x0750, PCI_MATCH_ANY, PCI_MATCH_ANY 144 }; 145 }; 146 147 class 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 169 std::unique_ptr<PciBridgeIntf> 170 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const override 171 { 172 return std::make_unique<AspeedPciBridge>(pci, skipBridgeDisable); 173 } 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 194 NuvotonDevice nuvotonDevice; 195 AspeedDevice aspeedDevice; 196 197 class PciSetupTest : public testing::TestWithParam<Device*> 198 {}; 199 200 /* Handle device not found */ 201 TEST_P(PciSetupTest, NotFound) 202 { 203 PciAccessMock pciMock; 204 205 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 */ 218 TEST_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 */ 238 TEST_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 */ 264 TEST_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 290 GetParam()->expectSetup(pciMock, dev); 291 // 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 */ 297 void expectSetup(PciAccessMock& pciMock, struct pci_device& dev, Device* param, 298 std::uint8_t* region, bool deviceExpectations = true) 299 { 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)); 319 320 EXPECT_CALL(pciMock, pci_device_enable(Eq(&dev))).Times(1); 321 322 if (deviceExpectations) 323 param->expectSetup(pciMock, dev); 324 } 325 326 /* Test finding device and mapping memory region */ 327 TEST_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 338 INSTANTIATE_TEST_SUITE_P(Default, PciSetupTest, 339 ::testing::Values(&nuvotonDevice, &aspeedDevice), 340 [](const testing::TestParamInfo<Device*>& info) { 341 return info.param->getName(); 342 }); 343 344 TEST(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 358 TEST(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>(®ion[0], data.size()), 373 SpanEq(stdplus::span<uint8_t>(data))); 374 } 375 376 TEST(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 392 TEST(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 404 /* Make sure config register is left alone if the bridge is already enabled */ 405 TEST(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 */ 439 TEST(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 */ 456 TEST(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 */ 480 TEST(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 */ 512 TEST(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 */ 549 TEST(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 559 /* Make sure it skips the disable bridge call when skipBridgeDisable is true */ 560 TEST(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 586 TEST(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 600 TEST(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>(®ion[0x10000], data.size()), 615 SpanEq(stdplus::span<uint8_t>(data))); 616 } 617 618 TEST(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>(®ion[AspeedDevice::bridge], sizeof(config)), 633 SpanEq(configSpan)); 634 } 635 636 TEST(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 */ 649 TEST(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 679 /* Make sure the config region remains the same even after cleanup if 680 * skipBridgeDisable is true */ 681 TEST(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 714 /* Make sure the bridge gets enabled when needed */ 715 TEST(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 } 743 } 744 745 } // namespace 746 } // namespace host_tool 747