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 <span> 27 #include <string> 28 #include <vector> 29 30 #include <gtest/gtest.h> 31 32 namespace host_tool 33 { 34 namespace 35 { 36 37 using namespace std::string_literals; 38 39 using ::testing::Assign; 40 using ::testing::ContainerEq; 41 using ::testing::DoAll; 42 using ::testing::Each; 43 using ::testing::Eq; 44 using ::testing::InSequence; 45 using ::testing::NotNull; 46 using ::testing::Return; 47 using ::testing::SetArgPointee; 48 49 // TODO: switch to ConainerEq for C++20 50 MATCHER_P(SpanEq, s, "") 51 { 52 return arg.size() == s.size() && !memcmp(arg.data(), s.data(), s.size()); 53 } 54 55 MATCHER_P(PciIdMatch, m, "") 56 { 57 return (arg->vendor_id == m->vendor_id && arg->device_id == m->device_id && 58 arg->subvendor_id == m->subvendor_id && 59 arg->subdevice_id == m->subdevice_id); 60 } 61 62 pci_device_iterator* mockIter = reinterpret_cast<pci_device_iterator*>(0x42); 63 64 constexpr pciaddr_t mockBaseAddr = 0xdeadbeef; 65 constexpr pciaddr_t mockRegionSize = 0x20000; 66 67 class Device 68 { 69 public: 70 virtual ~Device() = default; 71 virtual const struct pci_id_match* getMatch() const = 0; 72 virtual struct pci_device getDevice() const = 0; 73 virtual void expectSetup(PciAccessMock&, const struct pci_device&) 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, 0, 0, 0 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, 0, 0, 0 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(std::span<std::uint8_t>(data)), ToolException); 355 } 356 357 TEST(NuvotonWriteTest, Success) 358 { 359 PciAccessMock pciMock; 360 struct pci_device dev; 361 std::vector<std::uint8_t> region(mockRegionSize); 362 std::vector<std::uint8_t> data(0x4000); 363 364 std::generate(data.begin(), data.end(), std::rand); 365 366 expectSetup(pciMock, dev, &nuvotonDevice, region.data()); 367 368 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock); 369 bridge->write(std::span<std::uint8_t>(data)); 370 371 EXPECT_THAT(std::span<uint8_t>(®ion[0], data.size()), 372 SpanEq(std::span<uint8_t>(data))); 373 } 374 375 TEST(NuvotonConfigureTest, Success) 376 { 377 PciAccessMock pciMock; 378 struct pci_device dev; 379 std::vector<std::uint8_t> region(mockRegionSize); 380 ipmi_flash::PciConfigResponse config{0x123bea51}; 381 382 expectSetup(pciMock, dev, &nuvotonDevice, region.data()); 383 384 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock); 385 bridge->configure(config); 386 387 /* No effect from calling configure(), so the whole region should be 0 */ 388 EXPECT_THAT(region, Each(0)); 389 } 390 391 TEST(NuvotonDataLengthTest, Success) 392 { 393 PciAccessMock pciMock; 394 struct pci_device dev; 395 std::vector<std::uint8_t> region(mockRegionSize); 396 397 expectSetup(pciMock, dev, &nuvotonDevice, region.data()); 398 399 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock); 400 EXPECT_EQ(bridge->getDataLength(), 0x4000); 401 } 402 403 /* Make sure config register is left alone if the bridge is already enabled */ 404 TEST(NuvotonBridgeTest, AlreadyEnabledSuccess) 405 { 406 PciAccessMock pciMock; 407 struct pci_device dev; 408 std::vector<std::uint8_t> region(mockRegionSize); 409 410 constexpr std::uint8_t defaultVal = 0x40; 411 412 /* Only set standard expectations; not those from nuvotonDevice */ 413 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false); 414 415 { 416 InSequence in; 417 418 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(), 419 NuvotonDevice::config)) 420 .WillOnce(DoAll( 421 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled), 422 Return(0))); 423 424 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(), 425 NuvotonDevice::config)) 426 .WillOnce(DoAll( 427 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled), 428 Return(0))); 429 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal, 430 NuvotonDevice::config)) 431 .WillOnce(Return(0)); 432 } 433 434 nuvotonDevice.getBridge(&pciMock); 435 } 436 437 /* Read fails when attempting to setup the bridge */ 438 TEST(NuvotonBridgeTest, ReadSetupFail) 439 { 440 PciAccessMock pciMock; 441 struct pci_device dev; 442 std::vector<std::uint8_t> region(mockRegionSize); 443 444 /* Only set standard expectations; not those from nuvotonDevice */ 445 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false); 446 447 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(), 448 NuvotonDevice::config)) 449 .WillOnce(Return(EFAULT)); 450 451 EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error); 452 } 453 454 /* Write fails when attempting to setup the bridge */ 455 TEST(NuvotonBridgeTest, WriteSetupFail) 456 { 457 PciAccessMock pciMock; 458 struct pci_device dev; 459 std::vector<std::uint8_t> region(mockRegionSize); 460 461 constexpr std::uint8_t defaultVal = 0x40; 462 463 /* Only set standard expectations; not those from nuvotonDevice */ 464 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false); 465 466 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(), 467 NuvotonDevice::config)) 468 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0))); 469 EXPECT_CALL(pciMock, 470 pci_device_cfg_write_u8( 471 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled, 472 NuvotonDevice::config)) 473 .WillOnce(Return(EFAULT)); 474 475 EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error); 476 } 477 478 /* Read fails when attempting to disable the bridge */ 479 TEST(NuvotonBridgeTest, ReadDisableFail) 480 { 481 PciAccessMock pciMock; 482 struct pci_device dev; 483 std::vector<std::uint8_t> region(mockRegionSize); 484 485 constexpr std::uint8_t defaultVal = 0x40; 486 487 /* Only set standard expectations; not those from nuvotonDevice */ 488 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false); 489 490 { 491 InSequence in; 492 493 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(), 494 NuvotonDevice::config)) 495 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0))); 496 EXPECT_CALL(pciMock, 497 pci_device_cfg_write_u8( 498 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled, 499 NuvotonDevice::config)) 500 .WillOnce(Return(0)); 501 502 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(), 503 NuvotonDevice::config)) 504 .WillOnce(Return(EFAULT)); 505 } 506 507 nuvotonDevice.getBridge(&pciMock); 508 } 509 510 /* Write fails when attempting to disable the bridge */ 511 TEST(NuvotonBridgeTest, WriteDisableFail) 512 { 513 PciAccessMock pciMock; 514 struct pci_device dev; 515 std::vector<std::uint8_t> region(mockRegionSize); 516 517 constexpr std::uint8_t defaultVal = 0x40; 518 519 /* Only set standard expectations; not those from nuvotonDevice */ 520 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false); 521 522 { 523 InSequence in; 524 525 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(), 526 NuvotonDevice::config)) 527 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0))); 528 EXPECT_CALL(pciMock, 529 pci_device_cfg_write_u8( 530 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled, 531 NuvotonDevice::config)) 532 .WillOnce(Return(0)); 533 534 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(), 535 NuvotonDevice::config)) 536 .WillOnce(DoAll( 537 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled), 538 Return(0))); 539 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal, 540 NuvotonDevice::config)) 541 .WillOnce(Return(EFAULT)); 542 } 543 544 nuvotonDevice.getBridge(&pciMock); 545 } 546 547 /* Make sure the bridge gets enabled when needed */ 548 TEST(NuvotonBridgeTest, NotEnabledSuccess) 549 { 550 PciAccessMock pciMock; 551 struct pci_device dev; 552 std::vector<std::uint8_t> region(mockRegionSize); 553 554 expectSetup(pciMock, dev, &nuvotonDevice, region.data()); 555 nuvotonDevice.getBridge(&pciMock); 556 } 557 558 /* Make sure it skips the disable bridge call when skipBridgeDisable is true */ 559 TEST(NuvotonBridgeTest, SkipDisable) 560 { 561 PciAccessMock pciMock; 562 struct pci_device dev; 563 std::vector<std::uint8_t> region(mockRegionSize); 564 565 constexpr std::uint8_t defaultVal = 0x40; 566 567 /* Only set standard expectations; not those from nuvotonDevice */ 568 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false); 569 570 { 571 InSequence in; 572 573 /* Only expect call for enableBridge() */ 574 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(), 575 NuvotonDevice::config)) 576 .WillOnce(DoAll( 577 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled), 578 Return(0))); 579 } 580 581 /* Setting skipBridgeDisable to true */ 582 nuvotonDevice.getBridge(&pciMock, true); 583 } 584 585 TEST(AspeedWriteTest, TooLarge) 586 { 587 PciAccessMock pciMock; 588 struct pci_device dev; 589 std::vector<std::uint8_t> region(mockRegionSize); 590 std::vector<std::uint8_t> data(0x10001); 591 592 expectSetup(pciMock, dev, &aspeedDevice, region.data()); 593 594 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock); 595 EXPECT_THROW(bridge->write(std::span<std::uint8_t>(data)), ToolException); 596 } 597 598 TEST(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(std::span<std::uint8_t>(data)); 611 612 EXPECT_THAT(std::span<uint8_t>(®ion[0x10000], data.size()), 613 SpanEq(std::span<uint8_t>(data))); 614 } 615 616 TEST(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 std::span<uint8_t>(®ion[AspeedDevice::bridge], sizeof(config)), 631 SpanEq(configSpan)); 632 } 633 634 TEST(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 */ 647 TEST(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] = defaultVal | 664 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 677 /* Make sure the config region remains the same even after cleanup if 678 * skipBridgeDisable is true */ 679 TEST(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 = aspeedDevice.getBridge(&pciMock, 693 true); 694 695 { 696 std::vector<std::uint8_t> enabledRegion(mockRegionSize); 697 enabledRegion[AspeedDevice::config] = defaultVal | 698 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] = defaultVal | 707 AspeedDevice::bridgeEnabled; 708 EXPECT_THAT(region, ContainerEq(disabledRegion)); 709 } 710 } 711 712 /* Make sure the bridge gets enabled when needed */ 713 TEST(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] = defaultVal | 730 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 } 741 } 742 743 } // namespace 744 } // namespace host_tool 745