1/**
2 * Copyright(c) 2011 Trusted Logic.   All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 *  * Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 *  * Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in
12 *    the documentation and/or other materials provided with the
13 *    distribution.
14 *  * Neither the name Trusted Logic nor the names of its
15 *    contributors may be used to endorse or promote products derived
16 *    from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <stdlib.h>
32#include <stdio.h>
33#include <string.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#ifndef WIN32
37#include <sys/ioctl.h>
38#include <unistd.h>
39#endif
40#include <fcntl.h>
41#include <errno.h>
42
43#include "smc_pa_ctrl_os.h"
44#include "s_type.h"
45
46#ifndef BOOT_TIME_PA
47#define SMC_DRIVER_NAME    "/dev/tf_ctrl"
48#else
49#define SMC_DRIVER_NAME    "/dev/supervisor"
50#endif
51
52#define IOCTL_SCX_SMC_PA_CTRL \
53         _IOWR('z', 0xFF, SCX_SMC_PA_CTRL)
54
55
56typedef struct
57{
58   uint32_t nPACommand;       /* SCX_PA_CTRL_xxx */
59
60   /* For the SCX_SMC_PA_CTRL_START command only                           */
61   uint32_t nPASize;          /* PA buffer size                            */
62   uint8_t* pPABuffer;        /* PA buffer                                 */
63   uint32_t nConfSize;        /* Configuration buffer size, including the  */
64                              /* zero-terminating character (may be zero)  */
65   uint8_t* pConfBuffer;      /* Configuration buffer, zero-terminated     */
66                              /* string (may be NULL)                      */
67} SCX_SMC_PA_CTRL;
68
69static uint8_t* readLocalFile(const char* pFileName, uint32_t* pnBufferSize, bool bIsString)
70{
71   uint8_t* pBuffer = NULL;
72   FILE*    pFile = NULL;
73   uint32_t nBytesToAllocate;
74   int      nBytesRead;
75   int      nResult;
76
77   struct stat statFile;
78
79   *pnBufferSize = 0;
80
81   if (stat(pFileName, &statFile) != 0)
82   {
83      printf("Cannot read '%s' !\n", pFileName);
84      goto error;
85   }
86
87   nBytesToAllocate = statFile.st_size;
88
89   if (bIsString)
90   {
91      /* Allocate enough room for the zero-terminated string */
92      nBytesToAllocate ++;
93   }
94
95   pBuffer = (uint8_t*)malloc(nBytesToAllocate);
96   if (pBuffer == NULL)
97   {
98      printf("Out of memory for the buffer [%u bytes] !\n", nBytesToAllocate);
99      goto error;
100   }
101
102   pFile = fopen(pFileName, "rb");
103   if (pFile == NULL)
104   {
105      printf("Cannot open '%s' !\n", pFileName);
106      goto error;
107   }
108
109   nBytesRead = fread(pBuffer, 1, statFile.st_size, pFile);
110
111   if (nBytesRead != statFile.st_size)
112   {
113      printf("Cannot read bytes from '%s' [%i] !\n", pFileName, nBytesRead);
114      goto error;
115   }
116
117   nResult = fclose(pFile);
118
119   pFile = NULL;
120
121   if (nResult != 0)
122   {
123      printf("Cannot close '%s' !\n", pFileName);
124      goto error;
125   }
126
127   if (bIsString)
128   {
129      /* Set the zero-terminated string */
130      pBuffer[nBytesRead] = 0;
131   }
132
133   *pnBufferSize = nBytesToAllocate;
134
135   return pBuffer;
136
137   /*
138    * Error handling.
139    */
140
141error:
142   free(pBuffer);
143   if (pFile != NULL)
144   {
145      fclose(pFile);
146   }
147
148   return NULL;
149}
150
151
152
153
154int smcPAStart(const char* pPAFileName, const char* pConfFileName)
155{
156   int fd = 0;
157   int nStatus = 0;
158   SCX_SMC_PA_CTRL paCtrl;
159
160   memset(&paCtrl, 0, sizeof(SCX_SMC_PA_CTRL));
161   paCtrl.nPACommand = SCX_SMC_PA_CTRL_START;
162
163#ifdef BOOT_TIME_PA
164   printf("Starting the SMC BOOT PA '%s'. Driver name : %s", pPAFileName, SMC_DRIVER_NAME);
165#else
166   printf("Starting the SMC PA '%s'", pPAFileName);
167#endif
168   if (pConfFileName != NULL)
169   {
170      printf(" with the Configuration file '%s'", pConfFileName);
171   }
172   else
173   {
174      printf("Configuration file is mandatory\n");
175      nStatus  = -1;
176      goto end;
177   }
178   printf("...\n");
179
180   paCtrl.pPABuffer = readLocalFile(pPAFileName, &paCtrl.nPASize, false);
181   if (paCtrl.pPABuffer == NULL)
182   {
183      nStatus  = -2;
184      goto end;
185   }
186
187   paCtrl.pConfBuffer = readLocalFile(pConfFileName, &paCtrl.nConfSize, false);
188   if (paCtrl.pConfBuffer == NULL)
189   {
190      nStatus  = -4;
191      goto end;
192   }
193
194   #ifndef WIN32
195   fd = open(SMC_DRIVER_NAME, O_RDWR, 0);
196   #endif
197   if (fd == -1)
198   {
199      nStatus = errno;
200#ifdef BOOT_TIME_PA
201      printf("Boot time driver open failed [%d] !\n", nStatus);
202#else
203      printf("SMC driver open failed [%d] !\n", nStatus);
204#endif
205      goto end;
206   }
207
208   #ifndef WIN32
209   nStatus = ioctl(fd, IOCTL_SCX_SMC_PA_CTRL, &paCtrl);
210   #endif
211   if (nStatus != 0)
212   {
213      nStatus = errno;
214#ifdef BOOT_TIME_PA
215      printf("Starting the BOOT TIME PA failed [%d] !\n", nStatus);
216#else
217      printf("Starting the SMC PA failed [%d] !\n", nStatus);
218#endif
219      goto end;
220   }
221
222#ifdef BOOT_TIME_PA
223   printf("Boot time PA '%s' has been launched successfully.\n", pPAFileName);
224#else
225   printf("Starting the SMC PA '%s': Done\n", pPAFileName);
226#endif
227
228end:
229   if (fd != 0)
230   {
231      #ifndef WIN32
232      close(fd);
233      #endif
234   }
235
236   free(paCtrl.pPABuffer);
237   free(paCtrl.pConfBuffer);
238
239   return nStatus;
240}
241
242int smcPAStop(void)
243{
244   int fd = 0;
245   int nStatus = 0;
246   SCX_SMC_PA_CTRL paCtrl;
247
248   memset(&paCtrl, 0, sizeof(SCX_SMC_PA_CTRL));
249   paCtrl.nPACommand = SCX_SMC_PA_CTRL_STOP;
250
251   printf("Stopping the SMC PA...\n");
252
253   #ifndef WIN32
254   fd = open(SMC_DRIVER_NAME, O_RDWR, 0);
255   #endif
256   if (fd == 0)
257   {
258      nStatus = errno;
259      printf("SMC driver open failed [%d] !\n", nStatus);
260      goto end;
261   }
262
263   #ifndef WIN32
264   nStatus = ioctl(fd, IOCTL_SCX_SMC_PA_CTRL, &paCtrl);
265   #endif
266   if (nStatus != 0)
267   {
268      printf("Stopping the SMC PA failed [%d] !\n", nStatus);
269      goto end;
270   }
271
272   printf("Stopping the SMC PA: Done\n");
273
274end:
275
276   if (fd != 0)
277   {
278      #ifndef WIN32
279      close(fd);
280      #endif
281   }
282
283   return nStatus;
284}
285