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