1 // SPDX-License-Identifier: GPL-2.0-only
3 * Extensible SAL Interface (ESI) support routines.
5 * Copyright (C) 2006 Hewlett-Packard Co
6 * Alex Williamson <alex.williamson@hp.com>
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/module.h>
11 #include <linux/string.h>
16 MODULE_AUTHOR("Alex Williamson <alex.williamson@hp.com>");
17 MODULE_DESCRIPTION("Extensible SAL Interface (ESI) support");
18 MODULE_LICENSE("GPL");
20 #define MODULE_NAME "esi"
22 #define ESI_TABLE_GUID \
23 EFI_GUID(0x43EA58DC, 0xCF28, 0x4b06, 0xB3, \
24 0x91, 0xB7, 0x50, 0x59, 0x34, 0x2B, 0xD4)
26 enum esi_systab_entry_type
{
27 ESI_DESC_ENTRY_POINT
= 0
34 #define ESI_DESC_SIZE(type) "\060"[(unsigned) (type)]
36 typedef struct ia64_esi_desc_entry_point
{
42 } ia64_esi_desc_entry_point_t
;
49 static struct ia64_sal_systab
*esi_systab
;
51 static int __init
esi_init (void)
53 efi_config_table_t
*config_tables
;
54 struct ia64_sal_systab
*systab
;
55 unsigned long esi
= 0;
59 config_tables
= __va(efi
.systab
->tables
);
61 for (i
= 0; i
< (int) efi
.systab
->nr_tables
; ++i
) {
62 if (efi_guidcmp(config_tables
[i
].guid
, ESI_TABLE_GUID
) == 0) {
63 esi
= config_tables
[i
].table
;
73 if (strncmp(systab
->signature
, "ESIT", 4) != 0) {
74 printk(KERN_ERR
"bad signature in ESI system table!");
78 p
= (char *) (systab
+ 1);
79 for (i
= 0; i
< systab
->entry_count
; i
++) {
81 * The first byte of each entry type contains the type
85 case ESI_DESC_ENTRY_POINT
:
88 printk(KERN_WARNING
"Unknown table type %d found in "
89 "ESI table, ignoring rest of table\n", *p
);
93 p
+= ESI_DESC_SIZE(*p
);
101 int ia64_esi_call (efi_guid_t guid
, struct ia64_sal_retval
*isrvp
,
102 enum esi_proc_type proc_type
, u64 func
,
103 u64 arg1
, u64 arg2
, u64 arg3
, u64 arg4
, u64 arg5
, u64 arg6
,
106 struct ia64_fpreg fr
[6];
107 unsigned long flags
= 0;
114 p
= (char *) (esi_systab
+ 1);
115 for (i
= 0; i
< esi_systab
->entry_count
; i
++) {
116 if (*p
== ESI_DESC_ENTRY_POINT
) {
117 ia64_esi_desc_entry_point_t
*esi
= (void *)p
;
118 if (!efi_guidcmp(guid
, esi
->guid
)) {
119 ia64_sal_handler esi_proc
;
122 pdesc
.addr
= __va(esi
->esi_proc
);
123 pdesc
.gp
= __va(esi
->gp
);
125 esi_proc
= (ia64_sal_handler
) &pdesc
;
127 ia64_save_scratch_fpregs(fr
);
128 if (proc_type
== ESI_PROC_SERIALIZED
)
129 spin_lock_irqsave(&sal_lock
, flags
);
130 else if (proc_type
== ESI_PROC_MP_SAFE
)
131 local_irq_save(flags
);
134 *isrvp
= (*esi_proc
)(func
, arg1
, arg2
, arg3
,
135 arg4
, arg5
, arg6
, arg7
);
136 if (proc_type
== ESI_PROC_SERIALIZED
)
137 spin_unlock_irqrestore(&sal_lock
,
139 else if (proc_type
== ESI_PROC_MP_SAFE
)
140 local_irq_restore(flags
);
143 ia64_load_scratch_fpregs(fr
);
147 p
+= ESI_DESC_SIZE(*p
);
151 EXPORT_SYMBOL_GPL(ia64_esi_call
);
153 int ia64_esi_call_phys (efi_guid_t guid
, struct ia64_sal_retval
*isrvp
,
154 u64 func
, u64 arg1
, u64 arg2
, u64 arg3
, u64 arg4
,
155 u64 arg5
, u64 arg6
, u64 arg7
)
157 struct ia64_fpreg fr
[6];
166 p
= (char *) (esi_systab
+ 1);
167 for (i
= 0; i
< esi_systab
->entry_count
; i
++) {
168 if (*p
== ESI_DESC_ENTRY_POINT
) {
169 ia64_esi_desc_entry_point_t
*esi
= (void *)p
;
170 if (!efi_guidcmp(guid
, esi
->guid
)) {
171 ia64_sal_handler esi_proc
;
174 pdesc
.addr
= (void *)esi
->esi_proc
;
175 pdesc
.gp
= (void *)esi
->gp
;
177 esi_proc
= (ia64_sal_handler
) &pdesc
;
179 esi_params
[0] = func
;
180 esi_params
[1] = arg1
;
181 esi_params
[2] = arg2
;
182 esi_params
[3] = arg3
;
183 esi_params
[4] = arg4
;
184 esi_params
[5] = arg5
;
185 esi_params
[6] = arg6
;
186 esi_params
[7] = arg7
;
187 ia64_save_scratch_fpregs(fr
);
188 spin_lock_irqsave(&sal_lock
, flags
);
189 *isrvp
= esi_call_phys(esi_proc
, esi_params
);
190 spin_unlock_irqrestore(&sal_lock
, flags
);
191 ia64_load_scratch_fpregs(fr
);
195 p
+= ESI_DESC_SIZE(*p
);
199 EXPORT_SYMBOL_GPL(ia64_esi_call_phys
);
201 static void __exit
esi_exit (void)
205 module_init(esi_init
);
206 module_exit(esi_exit
); /* makes module removable... */