1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * AMD Platform Management Framework Test Tool
4 *
5 * Copyright (c) 2026, Advanced Micro Devices, Inc.
6 * All Rights Reserved.
7 *
8 * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
9 * Sanket Goswami <Sanket.Goswami@amd.com>
10 */
11
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <inttypes.h>
15 #include <stdbool.h>
16 #include <stdint.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <sys/ioctl.h>
20 #include <unistd.h>
21
22 #include <linux/amd-pmf.h>
23 #include <linux/kernel.h>
24
25 #define DEVICE_NODE "/dev/amdpmf_interface"
26
27 /* Feature flag names */
28 static const char * const feature_names[] = {
29 "Auto Mode",
30 "Static Power Slider",
31 "Policy Builder (Smart PC)",
32 "Dynamic Power Slider AC",
33 "Dynamic Power Slider DC",
34 };
35
36 static const char *banner =
37 "====================================================\n"
38 " AMD PMF Metrics info and Feature Status\n"
39 "====================================================\n\n";
40
41 /* Print feature flags */
pmf_print_features(uint32_t flags)42 static void pmf_print_features(uint32_t flags)
43 {
44 size_t i;
45
46 for (i = 0; i < ARRAY_SIZE(feature_names); i++)
47 printf(" [%c] %s\n", (flags & (1U << i)) ? 'x' : ' ', feature_names[i]);
48 }
49
50 /* Print BIOS parameters */
pmf_print_bios_params(const char * type,const __u32 * params)51 static void pmf_print_bios_params(const char *type, const __u32 *params)
52 {
53 int i;
54
55 for (i = 0; i < AMD_PMF_BIOS_PARAMS_MAX; i++)
56 printf(" Custom BIOS %s%d: %u\n", type, i + 1, params[i]);
57 }
58
59 /* Open the PMF device */
pmf_open_device(void)60 static int pmf_open_device(void)
61 {
62 int fd;
63
64 fd = open(DEVICE_NODE, O_RDONLY);
65 if (fd < 0)
66 fprintf(stderr, "Error: Cannot open %s: %s\n", DEVICE_NODE, strerror(errno));
67
68 return fd;
69 }
70
71 /* Query PMF info using the single IOCTL */
pmf_get_info(int fd,struct amd_pmf_info * info)72 static int pmf_get_info(int fd, struct amd_pmf_info *info)
73 {
74 int ret;
75
76 /* Zero-initialize and set size for versioning */
77 memset(info, 0, sizeof(*info));
78 info->size = sizeof(*info);
79
80 ret = ioctl(fd, IOCTL_AMD_PMF_POPULATE_DATA, info);
81 if (ret < 0) {
82 fprintf(stderr, "Error: IOCTL_AMD_PMF_POPULATE_DATA failed: %s\n", strerror(errno));
83 return ret;
84 }
85
86 return 0;
87 }
88
pmf_print_info(const struct amd_pmf_info * info)89 static void pmf_print_info(const struct amd_pmf_info *info)
90 {
91 printf("%s", banner);
92
93 /* Feature status */
94 printf("Feature Status:\n");
95 pmf_print_features(info->features_supported);
96
97 /* Device states */
98 printf("\nDevice States:\n");
99 printf(" Platform Type: %s\n", amd_pmf_get_platform_type(info->platform_type));
100 printf(" Laptop Placement: %s\n", amd_pmf_get_laptop_placement(info->laptop_placement));
101 printf(" Lid State: %s\n", info->lid_state ? "Closed" : "Open");
102 printf(" User Presence: %s\n", info->user_presence ? "Present" : "Away");
103 printf(" Slider Position: %s\n", amd_pmf_get_slider_position(info->slider_position));
104
105 /* Thermal and power metrics */
106 printf("\nThermal/Power Metrics:\n");
107 printf(" Skin Temperature: %d\n", info->skin_temp / 100);
108 printf(" GFX Busy: %u\n", info->gfx_busy);
109 printf(" Ambient Light: %d\n", info->ambient_light);
110 printf(" Avg C0 Residency: %u\n", info->avg_c0_residency);
111 printf(" Max C0 Residency: %u\n", info->max_c0_residency);
112 printf(" Socket Power: %u\n", info->socket_power);
113
114 /* BIOS parameters */
115 printf("\nCustom BIOS Input Parameters:\n");
116 pmf_print_bios_params("Input", info->bios_input);
117 printf("\nCustom BIOS Output Parameters:\n");
118 pmf_print_bios_params("Output", info->bios_output);
119
120 printf("\n=================================================\n");
121 }
122
main(void)123 int main(void)
124 {
125 struct amd_pmf_info info;
126 int fd, ret;
127
128 fd = pmf_open_device();
129 if (fd < 0)
130 return -1;
131
132 /* Query all info with single IOCTL */
133 ret = pmf_get_info(fd, &info);
134 close(fd);
135
136 if (ret < 0)
137 return -1;
138
139 pmf_print_info(&info);
140
141 return 0;
142 }
143