1/*	$NetBSD$	*/
2
3/*++
4
5Copyright (c) 1999  Intel Corporation
6
7Module Name:
8
9    salpal.c
10
11Abstract:
12
13    Functions to make SAL and PAL proc calls
14
15Revision History
16
17--*/
18#include "lib.h"
19#include "palproc.h"
20#include "salproc.h"
21/*++
22
23Copyright (c) 1999  Intel Corporation
24
25Module Name:
26
27    EfiRtLib.h
28
29Abstract:
30
31    EFI Runtime library functions
32
33
34
35Revision History
36
37--*/
38
39#include "efi.h"
40#include "efilib.h"
41
42rArg
43MakeStaticPALCall (
44    IN UINT64   PALPROCPtr,
45    IN UINT64   Arg1,
46    IN UINT64   Arg2,
47    IN UINT64   Arg3,
48    IN UINT64   Arg4
49    );
50
51rArg
52MakeStackedPALCall (
53    IN UINT64   PALPROCPtr,
54    IN UINT64   Arg1,
55    IN UINT64   Arg2,
56    IN UINT64   Arg3,
57    IN UINT64   Arg4
58    );
59
60
61PLABEL   SalProcPlabel;
62PLABEL   PalProcPlabel;
63CALL_SAL_PROC   GlobalSalProc;
64CALL_PAL_PROC   GlobalPalProc;
65
66VOID
67LibInitSalAndPalProc (
68    OUT PLABEL  *SalPlabel,
69    OUT UINT64  *PalEntry
70    )
71{
72    SAL_SYSTEM_TABLE_ASCENDING_ORDER    *SalSystemTable;
73    EFI_STATUS                          Status;
74
75    GlobalSalProc = NULL;
76    GlobalPalProc = NULL;
77
78    Status = LibGetSystemConfigurationTable(&SalSystemTableGuid, (VOID **)&SalSystemTable);
79    if (EFI_ERROR(Status)) {
80        return;
81    }
82
83    //
84    // BugBug: Add code to test checksum on the Sal System Table
85    //
86    if (SalSystemTable->Entry0.Type != 0) {
87        return;
88    }
89
90    SalProcPlabel.ProcEntryPoint = SalSystemTable->Entry0.SalProcEntry;
91    SalProcPlabel.GP             = SalSystemTable->Entry0.GlobalDataPointer;
92    GlobalSalProc                = (CALL_SAL_PROC)&SalProcPlabel.ProcEntryPoint;
93
94    //
95    // Need to check the PAL spec to make sure I'm not responsible for
96    //  storing more state.
97    // We are passing in a Plabel that should be ignorred by the PAL. Call
98    //  this way will cause use to retore our gp after the PAL returns.
99    //
100    PalProcPlabel.ProcEntryPoint = SalSystemTable->Entry0.PalProcEntry;
101    PalProcPlabel.GP             = SalSystemTable->Entry0.GlobalDataPointer;
102    GlobalPalProc                = (CALL_PAL_PROC)PalProcPlabel.ProcEntryPoint;
103
104    *PalEntry = PalProcPlabel.ProcEntryPoint;
105    *SalPlabel = SalProcPlabel;
106}
107
108EFI_STATUS
109LibGetSalIoPortMapping (
110    OUT UINT64  *IoPortMapping
111    )
112/*++
113
114  Get the IO Port Map from the SAL System Table.
115  DO NOT USE THIS TO DO YOU OWN IO's!!!!!!!!!!!!
116  Only use this for getting info, or initing the built in EFI IO abstraction.
117  Always use the EFI Device IO protoocl to access IO space.
118
119--*/
120{
121    SAL_SYSTEM_TABLE_ASCENDING_ORDER    *SalSystemTable;
122    SAL_ST_MEMORY_DESCRIPTOR_ENTRY      *SalMemDesc;
123    EFI_STATUS                          Status;
124
125    Status = LibGetSystemConfigurationTable(&SalSystemTableGuid, (VOID **)&SalSystemTable);
126    if (EFI_ERROR(Status)) {
127        return EFI_UNSUPPORTED;
128    }
129
130    //
131    // BugBug: Add code to test checksum on the Sal System Table
132    //
133    if (SalSystemTable->Entry0.Type != 0) {
134        return EFI_UNSUPPORTED;
135    }
136
137    //
138    // The SalSystemTable pointer includes the Type 0 entry.
139    //  The SalMemDesc is Type 1 so it comes next.
140    //
141    SalMemDesc = (SAL_ST_MEMORY_DESCRIPTOR_ENTRY *)(SalSystemTable + 1);
142    while (SalMemDesc->Type == SAL_ST_MEMORY_DESCRIPTOR) {
143        if (SalMemDesc->MemoryType == SAL_IO_PORT_MAPPING) {
144            *IoPortMapping = SalMemDesc->PhysicalMemoryAddress;
145            return EFI_SUCCESS;
146        }
147        SalMemDesc++;
148   }
149    return EFI_UNSUPPORTED;
150}
151
152EFI_STATUS
153LibGetSalIpiBlock (
154    OUT UINT64  *IpiBlock
155    )
156/*++
157
158  Get the IPI block from the SAL system table
159
160--*/
161{
162    SAL_SYSTEM_TABLE_ASCENDING_ORDER    *SalSystemTable;
163    SAL_ST_MEMORY_DESCRIPTOR_ENTRY      *SalMemDesc;
164    EFI_STATUS                          Status;
165
166    Status = LibGetSystemConfigurationTable(&SalSystemTableGuid, (VOID*)&SalSystemTable);
167    if (EFI_ERROR(Status)) {
168        return EFI_UNSUPPORTED;
169    }
170
171    //
172    // BugBug: Add code to test checksum on the Sal System Table
173    //
174    if (SalSystemTable->Entry0.Type != 0) {
175        return EFI_UNSUPPORTED;
176    }
177
178    //
179    // The SalSystemTable pointer includes the Type 0 entry.
180    //  The SalMemDesc is Type 1 so it comes next.
181    //
182    SalMemDesc = (SAL_ST_MEMORY_DESCRIPTOR_ENTRY *)(SalSystemTable + 1);
183    while (SalMemDesc->Type == SAL_ST_MEMORY_DESCRIPTOR) {
184        if (SalMemDesc->MemoryType == SAL_SAPIC_IPI_BLOCK ) {
185            *IpiBlock = SalMemDesc->PhysicalMemoryAddress;
186            return EFI_SUCCESS;
187        }
188        SalMemDesc++;
189    }
190    return EFI_UNSUPPORTED;
191}
192
193EFI_STATUS
194LibGetSalWakeupVector (
195    OUT UINT64  *WakeVector
196    )
197/*++
198
199Get the wakeup vector from the SAL system table
200
201--*/
202{
203    SAL_ST_AP_WAKEUP_DECRIPTOR      *ApWakeUp;
204
205    ApWakeUp = LibSearchSalSystemTable (SAL_ST_AP_WAKEUP);
206    if (!ApWakeUp) {
207        *WakeVector = -1;
208        return EFI_UNSUPPORTED;
209    }
210    *WakeVector = ApWakeUp->ExternalInterruptVector;
211    return EFI_SUCCESS;
212}
213
214VOID *
215LibSearchSalSystemTable (
216    IN  UINT8   EntryType
217    )
218{
219    EFI_STATUS                          Status;
220    UINT8                               *SalTableHack;
221    SAL_SYSTEM_TABLE_ASCENDING_ORDER    *SalSystemTable;
222    UINT16                              EntryCount;
223    UINT16                              Count;
224
225    Status = LibGetSystemConfigurationTable(&SalSystemTableGuid, (VOID*)&SalSystemTable);
226    if (EFI_ERROR(Status)) {
227        return NULL;
228    }
229
230    EntryCount = SalSystemTable->Header.EntryCount;
231    if (EntryCount == 0) {
232        return NULL;
233    }
234    //
235    // BugBug: Add code to test checksum on the Sal System Table
236    //
237
238    SalTableHack = (UINT8 *)&SalSystemTable->Entry0;
239    for (Count = 0; Count < EntryCount ;Count++) {
240        if (*SalTableHack == EntryType) {
241            return (VOID *)SalTableHack;
242        }
243        switch (*SalTableHack) {
244        case SAL_ST_ENTRY_POINT:
245            SalTableHack += 48;
246            break;
247        case SAL_ST_MEMORY_DESCRIPTOR:
248            SalTableHack += 32;
249            break;
250        case SAL_ST_PLATFORM_FEATURES:
251            SalTableHack += 16;
252            break;
253        case SAL_ST_TR_USAGE:
254            SalTableHack += 32;
255            break;
256        case SAL_ST_PTC:
257            SalTableHack += 16;
258            break;
259        case SAL_ST_AP_WAKEUP:
260            SalTableHack += 16;
261            break;
262        default:
263            ASSERT(FALSE);
264            break;
265        }
266    }
267    return NULL;
268}
269
270VOID
271LibSalProc (
272    IN  UINT64    Arg1,
273    IN  UINT64    Arg2,
274    IN  UINT64    Arg3,
275    IN  UINT64    Arg4,
276    IN  UINT64    Arg5,
277    IN  UINT64    Arg6,
278    IN  UINT64    Arg7,
279    IN  UINT64    Arg8,
280    OUT rArg      *Results  OPTIONAL
281    )
282{
283    rArg    ReturnValue;
284
285    ReturnValue.p0 = -3;    // SAL status return completed with error
286    if (GlobalSalProc) {
287        ReturnValue = GlobalSalProc(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8);
288    }
289
290    if (Results) {
291        CopyMem (Results, &ReturnValue, sizeof(rArg));
292    }
293}
294
295VOID
296LibPalProc (
297    IN  UINT64    Arg1, // Pal Proc index
298    IN  UINT64    Arg2,
299    IN  UINT64    Arg3,
300    IN  UINT64    Arg4,
301    OUT rArg      *Results  OPTIONAL
302    )
303{
304
305    rArg    ReturnValue;
306
307    ReturnValue.p0 = -3;    // PAL status return completed with error
308
309    //
310    // check for valid PalProc entry point
311    //
312
313    if (!GlobalPalProc) {
314        if (Results)
315            CopyMem (Results, &ReturnValue, sizeof(rArg));
316        return;
317    }
318
319    //
320    // check if index falls within stacked or static register calling conventions
321    // and call appropriate Pal stub call
322    //
323
324    if (((Arg1 >=255) && (Arg1 <=511)) ||
325        ((Arg1 >=768) && (Arg1 <=1023))) {
326            ReturnValue = MakeStackedPALCall((UINT64)GlobalPalProc,Arg1,Arg2,Arg3,Arg4);
327    }
328    else {
329        ReturnValue = MakeStaticPALCall((UINT64)GlobalPalProc,Arg1,Arg2,Arg3,Arg4);
330    }
331
332    if (Results)
333        CopyMem (Results, &ReturnValue, sizeof(rArg));
334
335    return;
336}
337
338