summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/logging/backend.cpp1
-rw-r--r--src/common/logging/log.h1
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/crypto/aes_util.cpp35
-rw-r--r--src/core/crypto/aes_util.h12
-rw-r--r--src/core/crypto/encryption_layer.h1
-rw-r--r--src/core/crypto/key_manager.cpp15
-rw-r--r--src/core/crypto/key_manager.h7
-rw-r--r--src/core/hle/service/arp/arp.cpp75
-rw-r--r--src/core/hle/service/arp/arp.h16
-rw-r--r--src/core/hle/service/audio/audin_a.cpp2
-rw-r--r--src/core/hle/service/audio/audrec_a.cpp2
-rw-r--r--src/core/hle/service/audio/audren_a.cpp2
-rw-r--r--src/core/hle/service/filesystem/fsp_ldr.cpp2
-rw-r--r--src/core/hle/service/filesystem/fsp_pr.cpp2
-rw-r--r--src/core/hle/service/service.cpp2
16 files changed, 132 insertions, 45 deletions
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 34dec06fe..816414e8d 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -168,6 +168,7 @@ void FileBackend::Write(const Entry& entry) {
168 SUB(Service, AM) \ 168 SUB(Service, AM) \
169 SUB(Service, AOC) \ 169 SUB(Service, AOC) \
170 SUB(Service, APM) \ 170 SUB(Service, APM) \
171 SUB(Service, ARP) \
171 SUB(Service, BCAT) \ 172 SUB(Service, BCAT) \
172 SUB(Service, BPC) \ 173 SUB(Service, BPC) \
173 SUB(Service, BTM) \ 174 SUB(Service, BTM) \
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index dd5c9e6be..7ab5277ea 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -54,6 +54,7 @@ enum class Class : ClassType {
54 Service_AM, ///< The AM (Applet manager) service 54 Service_AM, ///< The AM (Applet manager) service
55 Service_AOC, ///< The AOC (AddOn Content) service 55 Service_AOC, ///< The AOC (AddOn Content) service
56 Service_APM, ///< The APM (Performance) service 56 Service_APM, ///< The APM (Performance) service
57 Service_ARP, ///< The ARP service
57 Service_Audio, ///< The Audio (Audio control) service 58 Service_Audio, ///< The Audio (Audio control) service
58 Service_BCAT, ///< The BCAT service 59 Service_BCAT, ///< The BCAT service
59 Service_BPC, ///< The BPC service 60 Service_BPC, ///< The BPC service
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 28de22398..c11f017da 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -134,6 +134,8 @@ add_library(core STATIC
134 hle/service/apm/apm.h 134 hle/service/apm/apm.h
135 hle/service/apm/interface.cpp 135 hle/service/apm/interface.cpp
136 hle/service/apm/interface.h 136 hle/service/apm/interface.h
137 hle/service/arp/arp.cpp
138 hle/service/arp/arp.h
137 hle/service/audio/audctl.cpp 139 hle/service/audio/audctl.cpp
138 hle/service/audio/audctl.h 140 hle/service/audio/audctl.h
139 hle/service/audio/auddbg.cpp 141 hle/service/audio/auddbg.cpp
diff --git a/src/core/crypto/aes_util.cpp b/src/core/crypto/aes_util.cpp
index 4690af5f8..a9876c83e 100644
--- a/src/core/crypto/aes_util.cpp
+++ b/src/core/crypto/aes_util.cpp
@@ -3,10 +3,22 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <mbedtls/cipher.h> 5#include <mbedtls/cipher.h>
6#include "common/assert.h"
7#include "common/logging/log.h"
6#include "core/crypto/aes_util.h" 8#include "core/crypto/aes_util.h"
7#include "core/crypto/key_manager.h" 9#include "core/crypto/key_manager.h"
8 10
9namespace Core::Crypto { 11namespace Core::Crypto {
12namespace {
13std::vector<u8> CalculateNintendoTweak(size_t sector_id) {
14 std::vector<u8> out(0x10);
15 for (size_t i = 0xF; i <= 0xF; --i) {
16 out[i] = sector_id & 0xFF;
17 sector_id >>= 8;
18 }
19 return out;
20}
21} // Anonymous namespace
10 22
11static_assert(static_cast<size_t>(Mode::CTR) == static_cast<size_t>(MBEDTLS_CIPHER_AES_128_CTR), 23static_assert(static_cast<size_t>(Mode::CTR) == static_cast<size_t>(MBEDTLS_CIPHER_AES_128_CTR),
12 "CTR has incorrect value."); 24 "CTR has incorrect value.");
@@ -56,27 +68,28 @@ void AESCipher<Key, KeySize>::SetIV(std::vector<u8> iv) {
56} 68}
57 69
58template <typename Key, size_t KeySize> 70template <typename Key, size_t KeySize>
59void AESCipher<Key, KeySize>::Transcode(const u8* src, size_t size, u8* dest, Op op) { 71void AESCipher<Key, KeySize>::Transcode(const u8* src, size_t size, u8* dest, Op op) const {
60 size_t written = 0; 72 auto* const context = op == Op::Encrypt ? &ctx->encryption_context : &ctx->decryption_context;
61
62 const auto context = op == Op::Encrypt ? &ctx->encryption_context : &ctx->decryption_context;
63 73
64 mbedtls_cipher_reset(context); 74 mbedtls_cipher_reset(context);
65 75
76 size_t written = 0;
66 if (mbedtls_cipher_get_cipher_mode(context) == MBEDTLS_MODE_XTS) { 77 if (mbedtls_cipher_get_cipher_mode(context) == MBEDTLS_MODE_XTS) {
67 mbedtls_cipher_update(context, src, size, dest, &written); 78 mbedtls_cipher_update(context, src, size, dest, &written);
68 if (written != size) 79 if (written != size) {
69 LOG_WARNING(Crypto, "Not all data was decrypted requested={:016X}, actual={:016X}.", 80 LOG_WARNING(Crypto, "Not all data was decrypted requested={:016X}, actual={:016X}.",
70 size, written); 81 size, written);
82 }
71 } else { 83 } else {
72 const auto block_size = mbedtls_cipher_get_block_size(context); 84 const auto block_size = mbedtls_cipher_get_block_size(context);
73 85
74 for (size_t offset = 0; offset < size; offset += block_size) { 86 for (size_t offset = 0; offset < size; offset += block_size) {
75 auto length = std::min<size_t>(block_size, size - offset); 87 auto length = std::min<size_t>(block_size, size - offset);
76 mbedtls_cipher_update(context, src + offset, length, dest + offset, &written); 88 mbedtls_cipher_update(context, src + offset, length, dest + offset, &written);
77 if (written != length) 89 if (written != length) {
78 LOG_WARNING(Crypto, "Not all data was decrypted requested={:016X}, actual={:016X}.", 90 LOG_WARNING(Crypto, "Not all data was decrypted requested={:016X}, actual={:016X}.",
79 length, written); 91 length, written);
92 }
80 } 93 }
81 } 94 }
82 95
@@ -97,16 +110,6 @@ void AESCipher<Key, KeySize>::XTSTranscode(const u8* src, size_t size, u8* dest,
97 } 110 }
98} 111}
99 112
100template <typename Key, size_t KeySize>
101std::vector<u8> AESCipher<Key, KeySize>::CalculateNintendoTweak(size_t sector_id) {
102 std::vector<u8> out(0x10);
103 for (size_t i = 0xF; i <= 0xF; --i) {
104 out[i] = sector_id & 0xFF;
105 sector_id >>= 8;
106 }
107 return out;
108}
109
110template class AESCipher<Key128>; 113template class AESCipher<Key128>;
111template class AESCipher<Key256>; 114template class AESCipher<Key256>;
112} // namespace Core::Crypto \ No newline at end of file 115} // namespace Core::Crypto \ No newline at end of file
diff --git a/src/core/crypto/aes_util.h b/src/core/crypto/aes_util.h
index 5b0b02738..8ce9d6612 100644
--- a/src/core/crypto/aes_util.h
+++ b/src/core/crypto/aes_util.h
@@ -7,7 +7,7 @@
7#include <memory> 7#include <memory>
8#include <type_traits> 8#include <type_traits>
9#include <vector> 9#include <vector>
10#include "common/assert.h" 10#include "common/common_types.h"
11#include "core/file_sys/vfs.h" 11#include "core/file_sys/vfs.h"
12 12
13namespace Core::Crypto { 13namespace Core::Crypto {
@@ -38,15 +38,19 @@ public:
38 void SetIV(std::vector<u8> iv); 38 void SetIV(std::vector<u8> iv);
39 39
40 template <typename Source, typename Dest> 40 template <typename Source, typename Dest>
41 void Transcode(const Source* src, size_t size, Dest* dest, Op op) { 41 void Transcode(const Source* src, size_t size, Dest* dest, Op op) const {
42 static_assert(std::is_trivially_copyable_v<Source> && std::is_trivially_copyable_v<Dest>,
43 "Transcode source and destination types must be trivially copyable.");
42 Transcode(reinterpret_cast<const u8*>(src), size, reinterpret_cast<u8*>(dest), op); 44 Transcode(reinterpret_cast<const u8*>(src), size, reinterpret_cast<u8*>(dest), op);
43 } 45 }
44 46
45 void Transcode(const u8* src, size_t size, u8* dest, Op op); 47 void Transcode(const u8* src, size_t size, u8* dest, Op op) const;
46 48
47 template <typename Source, typename Dest> 49 template <typename Source, typename Dest>
48 void XTSTranscode(const Source* src, size_t size, Dest* dest, size_t sector_id, 50 void XTSTranscode(const Source* src, size_t size, Dest* dest, size_t sector_id,
49 size_t sector_size, Op op) { 51 size_t sector_size, Op op) {
52 static_assert(std::is_trivially_copyable_v<Source> && std::is_trivially_copyable_v<Dest>,
53 "XTSTranscode source and destination types must be trivially copyable.");
50 XTSTranscode(reinterpret_cast<const u8*>(src), size, reinterpret_cast<u8*>(dest), sector_id, 54 XTSTranscode(reinterpret_cast<const u8*>(src), size, reinterpret_cast<u8*>(dest), sector_id,
51 sector_size, op); 55 sector_size, op);
52 } 56 }
@@ -56,7 +60,5 @@ public:
56 60
57private: 61private:
58 std::unique_ptr<CipherContext> ctx; 62 std::unique_ptr<CipherContext> ctx;
59
60 static std::vector<u8> CalculateNintendoTweak(size_t sector_id);
61}; 63};
62} // namespace Core::Crypto 64} // namespace Core::Crypto
diff --git a/src/core/crypto/encryption_layer.h b/src/core/crypto/encryption_layer.h
index 71bca1f23..7f05af9b4 100644
--- a/src/core/crypto/encryption_layer.h
+++ b/src/core/crypto/encryption_layer.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h"
7#include "core/file_sys/vfs.h" 8#include "core/file_sys/vfs.h"
8 9
9namespace Core::Crypto { 10namespace Core::Crypto {
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index 678ac5752..fc45e7ab5 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -2,19 +2,16 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
5#include <array> 6#include <array>
6#include <fstream> 7#include <fstream>
7#include <locale> 8#include <locale>
8#include <sstream> 9#include <sstream>
9#include <string_view> 10#include <string_view>
10#include <mbedtls/sha256.h>
11#include "common/assert.h"
12#include "common/common_paths.h" 11#include "common/common_paths.h"
13#include "common/file_util.h" 12#include "common/file_util.h"
14#include "common/logging/log.h"
15#include "core/crypto/key_manager.h" 13#include "core/crypto/key_manager.h"
16#include "core/settings.h" 14#include "core/settings.h"
17#include "key_manager.h"
18 15
19namespace Core::Crypto { 16namespace Core::Crypto {
20 17
@@ -66,8 +63,7 @@ KeyManager::KeyManager() {
66 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "title.keys", true); 63 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "title.keys", true);
67} 64}
68 65
69void KeyManager::LoadFromFile(std::string_view filename_, bool is_title_keys) { 66void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
70 const auto filename = std::string(filename_);
71 std::ifstream file(filename); 67 std::ifstream file(filename);
72 if (!file.is_open()) 68 if (!file.is_open())
73 return; 69 return;
@@ -107,11 +103,8 @@ void KeyManager::LoadFromFile(std::string_view filename_, bool is_title_keys) {
107 } 103 }
108} 104}
109 105
110void KeyManager::AttemptLoadKeyFile(std::string_view dir1_, std::string_view dir2_, 106void KeyManager::AttemptLoadKeyFile(const std::string& dir1, const std::string& dir2,
111 std::string_view filename_, bool title) { 107 const std::string& filename, bool title) {
112 const std::string dir1(dir1_);
113 const std::string dir2(dir2_);
114 const std::string filename(filename_);
115 if (FileUtil::Exists(dir1 + DIR_SEP + filename)) 108 if (FileUtil::Exists(dir1 + DIR_SEP + filename))
116 LoadFromFile(dir1 + DIR_SEP + filename, title); 109 LoadFromFile(dir1 + DIR_SEP + filename, title);
117 else if (FileUtil::Exists(dir2 + DIR_SEP + filename)) 110 else if (FileUtil::Exists(dir2 + DIR_SEP + filename))
diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h
index 03152a12c..c4c53cefc 100644
--- a/src/core/crypto/key_manager.h
+++ b/src/core/crypto/key_manager.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <string>
8#include <type_traits> 9#include <type_traits>
9#include <unordered_map> 10#include <unordered_map>
10#include <vector> 11#include <vector>
@@ -109,9 +110,9 @@ private:
109 std::unordered_map<KeyIndex<S256KeyType>, Key256> s256_keys; 110 std::unordered_map<KeyIndex<S256KeyType>, Key256> s256_keys;
110 111
111 bool dev_mode; 112 bool dev_mode;
112 void LoadFromFile(std::string_view filename, bool is_title_keys); 113 void LoadFromFile(const std::string& filename, bool is_title_keys);
113 void AttemptLoadKeyFile(std::string_view dir1, std::string_view dir2, std::string_view filename, 114 void AttemptLoadKeyFile(const std::string& dir1, const std::string& dir2,
114 bool title); 115 const std::string& filename, bool title);
115 116
116 static const std::unordered_map<std::string, KeyIndex<S128KeyType>> s128_file_id; 117 static const std::unordered_map<std::string, KeyIndex<S128KeyType>> s128_file_id;
117 static const std::unordered_map<std::string, KeyIndex<S256KeyType>> s256_file_id; 118 static const std::unordered_map<std::string, KeyIndex<S256KeyType>> s256_file_id;
diff --git a/src/core/hle/service/arp/arp.cpp b/src/core/hle/service/arp/arp.cpp
new file mode 100644
index 000000000..358ef2576
--- /dev/null
+++ b/src/core/hle/service/arp/arp.cpp
@@ -0,0 +1,75 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <memory>
6
7#include "common/logging/log.h"
8#include "core/hle/ipc_helpers.h"
9#include "core/hle/kernel/hle_ipc.h"
10#include "core/hle/service/arp/arp.h"
11#include "core/hle/service/service.h"
12#include "core/hle/service/sm/sm.h"
13
14namespace Service::ARP {
15
16class ARP_R final : public ServiceFramework<ARP_R> {
17public:
18 explicit ARP_R() : ServiceFramework{"arp:r"} {
19 // clang-format off
20 static const FunctionInfo functions[] = {
21 {0, nullptr, "GetApplicationLaunchProperty"},
22 {1, nullptr, "GetApplicationLaunchPropertyWithApplicationId"},
23 {2, nullptr, "GetApplicationControlProperty"},
24 {3, nullptr, "GetApplicationControlPropertyWithApplicationId"},
25 };
26 // clang-format on
27
28 RegisterHandlers(functions);
29 }
30};
31
32class IRegistrar final : public ServiceFramework<IRegistrar> {
33public:
34 explicit IRegistrar() : ServiceFramework{"IRegistrar"} {
35 // clang-format off
36 static const FunctionInfo functions[] = {
37 {0, nullptr, "Issue"},
38 {1, nullptr, "SetApplicationLaunchProperty"},
39 {2, nullptr, "SetApplicationControlProperty"},
40 };
41 // clang-format on
42
43 RegisterHandlers(functions);
44 }
45};
46
47class ARP_W final : public ServiceFramework<ARP_W> {
48public:
49 explicit ARP_W() : ServiceFramework{"arp:w"} {
50 // clang-format off
51 static const FunctionInfo functions[] = {
52 {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"},
53 {1, nullptr, "DeleteProperties"},
54 };
55 // clang-format on
56
57 RegisterHandlers(functions);
58 }
59
60private:
61 void AcquireRegistrar(Kernel::HLERequestContext& ctx) {
62 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
63 rb.Push(RESULT_SUCCESS);
64 rb.PushIpcInterface<IRegistrar>();
65
66 LOG_DEBUG(Service_ARP, "called");
67 }
68};
69
70void InstallInterfaces(SM::ServiceManager& sm) {
71 std::make_shared<ARP_R>()->InstallAsService(sm);
72 std::make_shared<ARP_W>()->InstallAsService(sm);
73}
74
75} // namespace Service::ARP
diff --git a/src/core/hle/service/arp/arp.h b/src/core/hle/service/arp/arp.h
new file mode 100644
index 000000000..9d100187c
--- /dev/null
+++ b/src/core/hle/service/arp/arp.h
@@ -0,0 +1,16 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7namespace Service::SM {
8class ServiceManager;
9}
10
11namespace Service::ARP {
12
13/// Registers all ARP services with the specified service manager.
14void InstallInterfaces(SM::ServiceManager& sm);
15
16} // namespace Service::ARP
diff --git a/src/core/hle/service/audio/audin_a.cpp b/src/core/hle/service/audio/audin_a.cpp
index e62a27945..a70d5bca4 100644
--- a/src/core/hle/service/audio/audin_a.cpp
+++ b/src/core/hle/service/audio/audin_a.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once
6
7#include "core/hle/service/audio/audin_a.h" 5#include "core/hle/service/audio/audin_a.h"
8 6
9namespace Service::Audio { 7namespace Service::Audio {
diff --git a/src/core/hle/service/audio/audrec_a.cpp b/src/core/hle/service/audio/audrec_a.cpp
index 9c32f9b98..016eabf53 100644
--- a/src/core/hle/service/audio/audrec_a.cpp
+++ b/src/core/hle/service/audio/audrec_a.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once
6
7#include "core/hle/service/audio/audrec_a.h" 5#include "core/hle/service/audio/audrec_a.h"
8 6
9namespace Service::Audio { 7namespace Service::Audio {
diff --git a/src/core/hle/service/audio/audren_a.cpp b/src/core/hle/service/audio/audren_a.cpp
index bc9930d79..616ff3dc4 100644
--- a/src/core/hle/service/audio/audren_a.cpp
+++ b/src/core/hle/service/audio/audren_a.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once
6
7#include "core/hle/service/audio/audren_a.h" 5#include "core/hle/service/audio/audren_a.h"
8 6
9namespace Service::Audio { 7namespace Service::Audio {
diff --git a/src/core/hle/service/filesystem/fsp_ldr.cpp b/src/core/hle/service/filesystem/fsp_ldr.cpp
index ee6d4d055..0ab9c2606 100644
--- a/src/core/hle/service/filesystem/fsp_ldr.cpp
+++ b/src/core/hle/service/filesystem/fsp_ldr.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once
6
7#include "core/hle/service/filesystem/fsp_ldr.h" 5#include "core/hle/service/filesystem/fsp_ldr.h"
8#include "core/hle/service/service.h" 6#include "core/hle/service/service.h"
9 7
diff --git a/src/core/hle/service/filesystem/fsp_pr.cpp b/src/core/hle/service/filesystem/fsp_pr.cpp
index 0b51385ee..32b0ae454 100644
--- a/src/core/hle/service/filesystem/fsp_pr.cpp
+++ b/src/core/hle/service/filesystem/fsp_pr.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once
6
7#include "core/hle/service/filesystem/fsp_pr.h" 5#include "core/hle/service/filesystem/fsp_pr.h"
8#include "core/hle/service/service.h" 6#include "core/hle/service/service.h"
9 7
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 61e0c34a0..31ea79773 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -19,6 +19,7 @@
19#include "core/hle/service/am/am.h" 19#include "core/hle/service/am/am.h"
20#include "core/hle/service/aoc/aoc_u.h" 20#include "core/hle/service/aoc/aoc_u.h"
21#include "core/hle/service/apm/apm.h" 21#include "core/hle/service/apm/apm.h"
22#include "core/hle/service/arp/arp.h"
22#include "core/hle/service/audio/audio.h" 23#include "core/hle/service/audio/audio.h"
23#include "core/hle/service/bcat/bcat.h" 24#include "core/hle/service/bcat/bcat.h"
24#include "core/hle/service/bpc/bpc.h" 25#include "core/hle/service/bpc/bpc.h"
@@ -207,6 +208,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
207 AM::InstallInterfaces(*sm, nv_flinger); 208 AM::InstallInterfaces(*sm, nv_flinger);
208 AOC::InstallInterfaces(*sm); 209 AOC::InstallInterfaces(*sm);
209 APM::InstallInterfaces(*sm); 210 APM::InstallInterfaces(*sm);
211 ARP::InstallInterfaces(*sm);
210 Audio::InstallInterfaces(*sm); 212 Audio::InstallInterfaces(*sm);
211 BCAT::InstallInterfaces(*sm); 213 BCAT::InstallInterfaces(*sm);
212 BPC::InstallInterfaces(*sm); 214 BPC::InstallInterfaces(*sm);