mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	glue: Implement arp:w and arp:r services
These keep track of running process' launch properties and control properties and allows for issuing and reading them by process and title ID.
This commit is contained in:
		
							parent
							
								
									df3ee4f444
								
							
						
					
					
						commit
						ce21973022
					
				
							
								
								
									
										285
									
								
								src/core/hle/service/glue/arp.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								src/core/hle/service/glue/arp.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,285 @@
 | 
			
		||||
// Copyright 2018 yuzu emulator team
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "core/file_sys/control_metadata.h"
 | 
			
		||||
#include "core/hle/ipc_helpers.h"
 | 
			
		||||
#include "core/hle/kernel/hle_ipc.h"
 | 
			
		||||
#include "core/hle/kernel/kernel.h"
 | 
			
		||||
#include "core/hle/kernel/process.h"
 | 
			
		||||
#include "core/hle/service/glue/arp.h"
 | 
			
		||||
#include "core/hle/service/glue/errors.h"
 | 
			
		||||
#include "core/hle/service/glue/manager.h"
 | 
			
		||||
#include "core/hle/service/service.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::Glue {
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
std::optional<u64> GetTitleIDForProcessID(const Core::System& system, u64 process_id) {
 | 
			
		||||
    const auto& list = system.Kernel().GetProcessList();
 | 
			
		||||
    const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) {
 | 
			
		||||
        return process->GetProcessID() == process_id;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (iter == list.end()) {
 | 
			
		||||
        return std::nullopt;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (*iter)->GetTitleID();
 | 
			
		||||
}
 | 
			
		||||
} // Anonymous namespace
 | 
			
		||||
 | 
			
		||||
ARP_R::ARP_R(const Core::System& system, const ARPManager& manager)
 | 
			
		||||
    : ServiceFramework{"arp:r"}, system(system), manager(manager) {
 | 
			
		||||
    // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &ARP_R::GetApplicationLaunchProperty, "GetApplicationLaunchProperty"},
 | 
			
		||||
            {1, &ARP_R::GetApplicationLaunchPropertyWithApplicationId, "GetApplicationLaunchPropertyWithApplicationId"},
 | 
			
		||||
            {2, &ARP_R::GetApplicationControlProperty, "GetApplicationControlProperty"},
 | 
			
		||||
            {3, &ARP_R::GetApplicationControlPropertyWithApplicationId, "GetApplicationControlPropertyWithApplicationId"},
 | 
			
		||||
        };
 | 
			
		||||
    // clang-format on
 | 
			
		||||
 | 
			
		||||
    RegisterHandlers(functions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ARP_R::~ARP_R() = default;
 | 
			
		||||
 | 
			
		||||
void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto process_id = rp.PopRaw<u64>();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id);
 | 
			
		||||
 | 
			
		||||
    const auto title_id = GetTitleIDForProcessID(system, process_id);
 | 
			
		||||
    if (!title_id.has_value()) {
 | 
			
		||||
        LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!");
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ERR_NONEXISTENT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto res = manager.GetLaunchProperty(*title_id);
 | 
			
		||||
 | 
			
		||||
    if (res.Failed()) {
 | 
			
		||||
        LOG_ERROR(Service_ARP, "Failed to get launch property!");
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(res.Code());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 6};
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    rb.PushRaw(*res);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARP_R::GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto title_id = rp.PopRaw<u64>();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id);
 | 
			
		||||
 | 
			
		||||
    const auto res = manager.GetLaunchProperty(title_id);
 | 
			
		||||
 | 
			
		||||
    if (res.Failed()) {
 | 
			
		||||
        LOG_ERROR(Service_ARP, "Failed to get launch property!");
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(res.Code());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 6};
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    rb.PushRaw(*res);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto process_id = rp.PopRaw<u64>();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id);
 | 
			
		||||
 | 
			
		||||
    const auto title_id = GetTitleIDForProcessID(system, process_id);
 | 
			
		||||
    if (!title_id.has_value()) {
 | 
			
		||||
        LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!");
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ERR_NONEXISTENT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto res = manager.GetControlProperty(*title_id);
 | 
			
		||||
 | 
			
		||||
    if (res.Failed()) {
 | 
			
		||||
        LOG_ERROR(Service_ARP, "Failed to get control property!");
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(res.Code());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ctx.WriteBuffer(*res);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARP_R::GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto title_id = rp.PopRaw<u64>();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id);
 | 
			
		||||
 | 
			
		||||
    const auto res = manager.GetControlProperty(title_id);
 | 
			
		||||
 | 
			
		||||
    if (res.Failed()) {
 | 
			
		||||
        LOG_ERROR(Service_ARP, "Failed to get control property!");
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(res.Code());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ctx.WriteBuffer(*res);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class IRegistrar final : public ServiceFramework<IRegistrar> {
 | 
			
		||||
    friend class ARP_W;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit IRegistrar(
 | 
			
		||||
        std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)> issuer)
 | 
			
		||||
        : ServiceFramework{"IRegistrar"}, issue_process_id(std::move(issuer)) {
 | 
			
		||||
        // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &IRegistrar::Issue, "Issue"},
 | 
			
		||||
            {1, &IRegistrar::SetApplicationLaunchProperty, "SetApplicationLaunchProperty"},
 | 
			
		||||
            {2, &IRegistrar::SetApplicationControlProperty, "SetApplicationControlProperty"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void Issue(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        IPC::RequestParser rp{ctx};
 | 
			
		||||
        const auto process_id = rp.PopRaw<u64>();
 | 
			
		||||
 | 
			
		||||
        LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id);
 | 
			
		||||
 | 
			
		||||
        if (process_id == 0) {
 | 
			
		||||
            LOG_ERROR(Service_ARP, "Must have non-zero process ID!");
 | 
			
		||||
            IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
            rb.Push(ERR_PROCESS_ID_ZERO);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (issued) {
 | 
			
		||||
            LOG_ERROR(Service_ARP,
 | 
			
		||||
                      "Attempted to issue registrar, but registrar is already issued!");
 | 
			
		||||
            IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
            rb.Push(ERR_ALREADY_ISSUED);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        issue_process_id(process_id, launch, std::move(control));
 | 
			
		||||
        issued = true;
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        LOG_DEBUG(Service_ARP, "called");
 | 
			
		||||
 | 
			
		||||
        if (issued) {
 | 
			
		||||
            LOG_ERROR(
 | 
			
		||||
                Service_ARP,
 | 
			
		||||
                "Attempted to set application launch property, but registrar is already issued!");
 | 
			
		||||
            IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
            rb.Push(ERR_ALREADY_ISSUED);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        IPC::RequestParser rp{ctx};
 | 
			
		||||
        launch = rp.PopRaw<ApplicationLaunchProperty>();
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SetApplicationControlProperty(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        LOG_DEBUG(Service_ARP, "called");
 | 
			
		||||
 | 
			
		||||
        if (issued) {
 | 
			
		||||
            LOG_ERROR(
 | 
			
		||||
                Service_ARP,
 | 
			
		||||
                "Attempted to set application control property, but registrar is already issued!");
 | 
			
		||||
            IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
            rb.Push(ERR_ALREADY_ISSUED);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        control = ctx.ReadBuffer();
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)> issue_process_id;
 | 
			
		||||
    bool issued = false;
 | 
			
		||||
    ApplicationLaunchProperty launch;
 | 
			
		||||
    std::vector<u8> control;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ARP_W::ARP_W(const Core::System& system, ARPManager& manager)
 | 
			
		||||
    : ServiceFramework{"arp:w"}, system(system), manager(manager) {
 | 
			
		||||
    // clang-format off
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"},
 | 
			
		||||
            {1, &ARP_W::DeleteProperties, "DeleteProperties"},
 | 
			
		||||
        };
 | 
			
		||||
    // clang-format on
 | 
			
		||||
 | 
			
		||||
    RegisterHandlers(functions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ARP_W::~ARP_W() = default;
 | 
			
		||||
 | 
			
		||||
void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    LOG_DEBUG(Service_ARP, "called");
 | 
			
		||||
 | 
			
		||||
    registrar = std::make_shared<IRegistrar>(
 | 
			
		||||
        [this](u64 process_id, ApplicationLaunchProperty launch, std::vector<u8> control) {
 | 
			
		||||
            const auto res = GetTitleIDForProcessID(system, process_id);
 | 
			
		||||
            if (!res.has_value()) {
 | 
			
		||||
                return ERR_NONEXISTENT;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return manager.Register(*res, launch, std::move(control));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    rb.PushIpcInterface(registrar);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto process_id = rp.PopRaw<u64>();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id);
 | 
			
		||||
 | 
			
		||||
    if (process_id == 0) {
 | 
			
		||||
        LOG_ERROR(Service_ARP, "Must have non-zero process ID!");
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ERR_PROCESS_ID_ZERO);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto title_id = GetTitleIDForProcessID(system, process_id);
 | 
			
		||||
 | 
			
		||||
    if (!title_id.has_value()) {
 | 
			
		||||
        LOG_ERROR(Service_ARP, "No title ID for process ID!");
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ERR_NONEXISTENT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(manager.Unregister(*title_id));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::Glue
 | 
			
		||||
							
								
								
									
										43
									
								
								src/core/hle/service/glue/arp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/core/hle/service/glue/arp.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
			
		||||
// Copyright 2019 yuzu emulator team
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "core/hle/service/service.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::Glue {
 | 
			
		||||
 | 
			
		||||
class ARPManager;
 | 
			
		||||
class IRegistrar;
 | 
			
		||||
 | 
			
		||||
class ARP_R final : public ServiceFramework<ARP_R> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit ARP_R(const Core::System& system, const ARPManager& manager);
 | 
			
		||||
    ~ARP_R() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void GetApplicationControlProperty(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
    const Core::System& system;
 | 
			
		||||
    const ARPManager& manager;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ARP_W final : public ServiceFramework<ARP_W> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit ARP_W(const Core::System& system, ARPManager& manager);
 | 
			
		||||
    ~ARP_W() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void AcquireRegistrar(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void DeleteProperties(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
    const Core::System& system;
 | 
			
		||||
    ARPManager& manager;
 | 
			
		||||
    std::shared_ptr<IRegistrar> registrar;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Service::Glue
 | 
			
		||||
@ -19,7 +19,6 @@
 | 
			
		||||
#include "core/hle/service/am/am.h"
 | 
			
		||||
#include "core/hle/service/aoc/aoc_u.h"
 | 
			
		||||
#include "core/hle/service/apm/apm.h"
 | 
			
		||||
#include "core/hle/service/arp/arp.h"
 | 
			
		||||
#include "core/hle/service/audio/audio.h"
 | 
			
		||||
#include "core/hle/service/bcat/module.h"
 | 
			
		||||
#include "core/hle/service/bpc/bpc.h"
 | 
			
		||||
@ -33,6 +32,7 @@
 | 
			
		||||
#include "core/hle/service/fgm/fgm.h"
 | 
			
		||||
#include "core/hle/service/filesystem/filesystem.h"
 | 
			
		||||
#include "core/hle/service/friend/friend.h"
 | 
			
		||||
#include "core/hle/service/glue/glue.h"
 | 
			
		||||
#include "core/hle/service/grc/grc.h"
 | 
			
		||||
#include "core/hle/service/hid/hid.h"
 | 
			
		||||
#include "core/hle/service/lbl/lbl.h"
 | 
			
		||||
@ -207,7 +207,6 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,
 | 
			
		||||
    AM::InstallInterfaces(*sm, nv_flinger);
 | 
			
		||||
    AOC::InstallInterfaces(*sm);
 | 
			
		||||
    APM::InstallInterfaces(*sm);
 | 
			
		||||
    ARP::InstallInterfaces(*sm);
 | 
			
		||||
    Audio::InstallInterfaces(*sm);
 | 
			
		||||
    BCAT::InstallInterfaces(*sm);
 | 
			
		||||
    BPC::InstallInterfaces(*sm);
 | 
			
		||||
@ -221,6 +220,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,
 | 
			
		||||
    FGM::InstallInterfaces(*sm);
 | 
			
		||||
    FileSystem::InstallInterfaces(*sm, vfs);
 | 
			
		||||
    Friend::InstallInterfaces(*sm);
 | 
			
		||||
    Glue::InstallInterfaces(system);
 | 
			
		||||
    GRC::InstallInterfaces(*sm);
 | 
			
		||||
    HID::InstallInterfaces(*sm);
 | 
			
		||||
    LBL::InstallInterfaces(*sm);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user