1 /** @file
2 
3 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5 
6 
7 **/
8 
9 #include "Edb.h"
10 
11 /**
12 
13   Check whether current IP is EBC BREAK3 instruction.
14 
15   @param  Address    EBC IP address.
16 
17   @retval TRUE       Current IP is EBC BREAK3 instruction
18   @retval FALSE      Current IP is not EBC BREAK3 instruction
19 
20 **/
21 BOOLEAN
IsEBCBREAK3(IN UINTN Address)22 IsEBCBREAK3 (
23   IN UINTN            Address
24   )
25 {
26   if (GET_OPCODE(Address) != OPCODE_BREAK) {
27     return FALSE;
28   }
29 
30   if (GET_OPERANDS (Address) != 3) {
31     return FALSE;
32   } else {
33     return TRUE;
34   }
35 }
36 
37 /**
38 
39   Check whether the Address is already set in breakpoint.
40 
41   @param  DebuggerPrivate   EBC Debugger private data structure
42   @param  Address           Breakpoint Address
43 
44   @retval TRUE              breakpoint is found
45   @retval FALSE             breakpoint is not found
46 
47 **/
48 BOOLEAN
DebuggerBreakpointIsDuplicated(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN UINTN Address)49 DebuggerBreakpointIsDuplicated (
50   IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
51   IN UINTN                     Address
52   )
53 {
54   UINTN  Index;
55 
56   //
57   // Go through each breakpoint context
58   //
59   for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) {
60     if (DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) {
61       //
62       // Found it
63       //
64       return TRUE;
65     }
66   }
67 
68   //
69   // Not found
70   //
71   return FALSE;
72 }
73 
74 /**
75 
76   Add this breakpoint.
77 
78   @param  DebuggerPrivate   EBC Debugger private data structure
79   @param  Address           Breakpoint Address
80 
81   @retval EFI_SUCCESS            breakpoint added successfully
82   @retval EFI_ALREADY_STARTED    breakpoint is already added
83   @retval EFI_OUT_OF_RESOURCES   all the breakpoint entries are used
84 
85 **/
86 EFI_STATUS
DebuggerBreakpointAdd(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN UINTN Address)87 DebuggerBreakpointAdd (
88   IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
89   IN UINTN                     Address
90   )
91 {
92   //
93   // Check duplicated breakpoint
94   //
95   if (DebuggerBreakpointIsDuplicated (DebuggerPrivate, Address)) {
96     EDBPrint (L"Breakpoint duplicated!\n");
97     return EFI_ALREADY_STARTED;
98   }
99 
100   //
101   // Check whether the address is a breakpoint 3 instruction
102   //
103   if (IsEBCBREAK3 (Address)) {
104     EDBPrint (L"Breakpoint can not be set on BREAK 3 instruction!\n");
105     return EFI_ALREADY_STARTED;
106   }
107 
108   if (DebuggerPrivate->DebuggerBreakpointCount >= EFI_DEBUGGER_BREAKPOINT_MAX) {
109     EDBPrint (L"Breakpoint out of resource!\n");
110     return EFI_OUT_OF_RESOURCES;
111   }
112 
113   //
114   // Set the breakpoint
115   //
116   DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].BreakpointAddress = Address;
117   DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].State = TRUE;
118   DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].OldInstruction = 0;
119   CopyMem (
120     &DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].OldInstruction,
121     (VOID *)Address,
122     sizeof(UINT16)
123     );
124 
125   DebuggerPrivate->DebuggerBreakpointCount ++;
126 
127   //
128   // Done
129   //
130   return EFI_SUCCESS;
131 }
132 
133 /**
134 
135   Delete this breakpoint.
136 
137   @param  DebuggerPrivate   EBC Debugger private data structure
138   @param  Index             Breakpoint Index
139 
140   @retval EFI_SUCCESS     breakpoint deleted successfully
141   @retval EFI_NOT_FOUND   breakpoint not found
142 
143 **/
144 EFI_STATUS
DebuggerBreakpointDel(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN UINTN Index)145 DebuggerBreakpointDel (
146   IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
147   IN UINTN                     Index
148   )
149 {
150   UINTN    BpIndex;
151 
152   if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) ||
153       (Index >= DebuggerPrivate->DebuggerBreakpointCount)) {
154     return EFI_NOT_FOUND;
155   }
156 
157   //
158   // Delete this breakpoint
159   //
160   for (BpIndex = Index; BpIndex < DebuggerPrivate->DebuggerBreakpointCount - 1; BpIndex++) {
161     DebuggerPrivate->DebuggerBreakpointContext[BpIndex] = DebuggerPrivate->DebuggerBreakpointContext[BpIndex + 1];
162   }
163   ZeroMem (
164     &DebuggerPrivate->DebuggerBreakpointContext[BpIndex],
165     sizeof(DebuggerPrivate->DebuggerBreakpointContext[BpIndex])
166     );
167 
168   DebuggerPrivate->DebuggerBreakpointCount --;
169 
170   //
171   // Done
172   //
173   return EFI_SUCCESS;
174 }
175 
176 /**
177 
178   Disable this breakpoint.
179 
180   @param  DebuggerPrivate   EBC Debugger private data structure
181   @param  Index             Breakpoint Index
182 
183   @retval EFI_SUCCESS     breakpoint disabled successfully
184   @retval EFI_NOT_FOUND   breakpoint not found
185 
186 **/
187 EFI_STATUS
DebuggerBreakpointDis(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN UINTN Index)188 DebuggerBreakpointDis (
189   IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
190   IN UINTN                     Index
191   )
192 {
193   if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) ||
194       (Index >= DebuggerPrivate->DebuggerBreakpointCount)) {
195     return EFI_NOT_FOUND;
196   }
197 
198   //
199   // Disable this breakpoint
200   //
201   DebuggerPrivate->DebuggerBreakpointContext[Index].State = FALSE;
202 
203   return EFI_SUCCESS;
204 }
205 
206 /**
207 
208   Enable this breakpoint.
209 
210   @param  DebuggerPrivate - EBC Debugger private data structure
211   @param  Index           - Breakpoint Index
212 
213   @retval EFI_SUCCESS   - breakpoint enabled successfully
214   @retval EFI_NOT_FOUND - breakpoint not found
215 
216 **/
217 EFI_STATUS
DebuggerBreakpointEn(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN UINTN Index)218 DebuggerBreakpointEn (
219   IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
220   IN UINTN                     Index
221   )
222 {
223   if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) ||
224       (Index >= DebuggerPrivate->DebuggerBreakpointCount)) {
225     return EFI_NOT_FOUND;
226   }
227 
228   //
229   // Enable this breakpoint
230   //
231   DebuggerPrivate->DebuggerBreakpointContext[Index].State = TRUE;
232 
233   return EFI_SUCCESS;
234 }
235 
236 /**
237 
238   DebuggerCommand - BreakpointList.
239 
240   @param  CommandArg      - The argument for this command
241   @param  DebuggerPrivate - EBC Debugger private data structure
242   @param  ExceptionType   - Exception type.
243   @param  SystemContext   - EBC system context.
244 
245   @retval EFI_DEBUG_CONTINUE - formal return value
246 
247 **/
248 EFI_DEBUG_STATUS
DebuggerBreakpointList(IN CHAR16 * CommandArg,IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_EXCEPTION_TYPE ExceptionType,IN OUT EFI_SYSTEM_CONTEXT SystemContext)249 DebuggerBreakpointList (
250   IN     CHAR16                    *CommandArg,
251   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
252   IN     EFI_EXCEPTION_TYPE        ExceptionType,
253   IN OUT EFI_SYSTEM_CONTEXT        SystemContext
254   )
255 {
256   UINTN Index;
257 
258   //
259   // Check breakpoint cound
260   //
261   if (DebuggerPrivate->DebuggerBreakpointCount == 0) {
262     EDBPrint (L"No Breakpoint\n");
263     return EFI_DEBUG_CONTINUE;
264   } else if (DebuggerPrivate->DebuggerBreakpointCount > EFI_DEBUGGER_BREAKPOINT_MAX) {
265     EDBPrint (L"Breakpoint too many!\n");
266     DebuggerPrivate->DebuggerBreakpointCount = 0;
267     return EFI_DEBUG_CONTINUE;
268   }
269 
270   //
271   // Go through each breakpoint
272   //
273   EDBPrint (L"Breakpoint :\n");
274   EDBPrint (L" Index   Address            Status\n");
275   EDBPrint (L"======= ================== ========\n");
276 //EDBPrint (L"   1    0xFFFFFFFF00000000    *\n");
277 //EDBPrint (L"  12    0x00000000FFFFFFFF\n");
278   for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) {
279     //
280     // Print the breakpoint
281     //
282     EDBPrint (L"  %2d    0x%016lx", Index, DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress);
283     if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) {
284       EDBPrint (L"    *\n");
285     } else {
286       EDBPrint (L"\n");
287     }
288   }
289 
290   //
291   // Done
292   //
293   return EFI_DEBUG_CONTINUE;
294 }
295 
296 /**
297 
298   DebuggerCommand - BreakpointSet.
299 
300   @param  CommandArg        The argument for this command
301   @param  DebuggerPrivate   EBC Debugger private data structure
302   @param  ExceptionType     Exception type.
303   @param  SystemContext     EBC system context.
304 
305   @retval EFI_DEBUG_CONTINUE - formal return value
306 
307 **/
308 EFI_DEBUG_STATUS
DebuggerBreakpointSet(IN CHAR16 * CommandArg,IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_EXCEPTION_TYPE ExceptionType,IN OUT EFI_SYSTEM_CONTEXT SystemContext)309 DebuggerBreakpointSet (
310   IN     CHAR16                    *CommandArg,
311   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
312   IN     EFI_EXCEPTION_TYPE        ExceptionType,
313   IN OUT EFI_SYSTEM_CONTEXT        SystemContext
314   )
315 {
316   UINTN      Address;
317   EFI_STATUS Status;
318 
319   if (CommandArg == NULL) {
320     EDBPrint (L"BreakpointSet Argument error!\n");
321     return EFI_DEBUG_CONTINUE;
322   }
323 
324   //
325   // Get breakpoint address
326   //
327   Status = Symboltoi (CommandArg, &Address);
328   if (EFI_ERROR (Status)) {
329     if (Status == EFI_NOT_FOUND) {
330       Address = Xtoi(CommandArg);
331     } else {
332       //
333       // Something wrong, let Symboltoi print error info.
334       //
335       EDBPrint (L"Command Argument error!\n");
336       return EFI_DEBUG_CONTINUE;
337     }
338   }
339 
340   //
341   // Add breakpoint
342   //
343   Status = DebuggerBreakpointAdd (DebuggerPrivate, Address);
344   if (EFI_ERROR(Status)) {
345     EDBPrint (L"BreakpointSet error!\n");
346   }
347 
348   //
349   // Done
350   //
351   return EFI_DEBUG_CONTINUE;
352 }
353 
354 /**
355 
356   DebuggerCommand - BreakpointClear
357 
358   @param  CommandArg        The argument for this command
359   @param  DebuggerPrivate   EBC Debugger private data structure
360   @param  ExceptionType     Exception type.
361   @param  SystemContext     EBC system context.
362 
363   @retval EFI_DEBUG_CONTINUE   formal return value
364 
365 **/
366 EFI_DEBUG_STATUS
DebuggerBreakpointClear(IN CHAR16 * CommandArg,IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_EXCEPTION_TYPE ExceptionType,IN OUT EFI_SYSTEM_CONTEXT SystemContext)367 DebuggerBreakpointClear (
368   IN     CHAR16                    *CommandArg,
369   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
370   IN     EFI_EXCEPTION_TYPE        ExceptionType,
371   IN OUT EFI_SYSTEM_CONTEXT        SystemContext
372   )
373 {
374   UINTN      Index;
375   EFI_STATUS Status;
376 
377   if (CommandArg == NULL) {
378     EDBPrint (L"BreakpointClear Argument error!\n");
379     return EFI_DEBUG_CONTINUE;
380   }
381 
382   if (StriCmp (CommandArg, L"*") == 0) {
383     //
384     // delete all breakpoint
385     //
386     DebuggerPrivate->DebuggerBreakpointCount = 0;
387     ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof(DebuggerPrivate->DebuggerBreakpointContext));
388     EDBPrint (L"All the Breakpoint is cleared\n");
389     return EFI_DEBUG_CONTINUE;
390   }
391 
392   //
393   // Get breakpoint index
394   //
395   Index = Atoi(CommandArg);
396   if (Index == (UINTN) -1) {
397     EDBPrint (L"BreakpointClear Argument error!\n");
398     return EFI_DEBUG_CONTINUE;
399   }
400 
401   if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) ||
402       (Index >= DebuggerPrivate->DebuggerBreakpointCount)) {
403     EDBPrint (L"BreakpointClear error!\n");
404     return EFI_DEBUG_CONTINUE;
405   }
406 
407   //
408   // Delete breakpoint
409   //
410   Status = DebuggerBreakpointDel (DebuggerPrivate, Index);
411   if (EFI_ERROR(Status)) {
412     EDBPrint (L"BreakpointClear error!\n");
413   }
414 
415   //
416   // Done
417   //
418   return EFI_DEBUG_CONTINUE;
419 }
420 
421 /**
422 
423   DebuggerCommand - BreakpointDisable
424 
425   @param  CommandArg        The argument for this command
426   @param  DebuggerPrivate   EBC Debugger private data structure
427   @param  ExceptionType     Exception type.
428   @param  SystemContext     EBC system context.
429 
430   @retval EFI_DEBUG_CONTINUE   formal return value
431 
432 **/
433 EFI_DEBUG_STATUS
DebuggerBreakpointDisable(IN CHAR16 * CommandArg,IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_EXCEPTION_TYPE ExceptionType,IN OUT EFI_SYSTEM_CONTEXT SystemContext)434 DebuggerBreakpointDisable (
435   IN     CHAR16                    *CommandArg,
436   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
437   IN     EFI_EXCEPTION_TYPE        ExceptionType,
438   IN OUT EFI_SYSTEM_CONTEXT        SystemContext
439   )
440 {
441   UINTN      Index;
442   EFI_STATUS Status;
443 
444   if (CommandArg == NULL) {
445     EDBPrint (L"BreakpointDisable Argument error!\n");
446     return EFI_DEBUG_CONTINUE;
447   }
448 
449   if (StriCmp (CommandArg, L"*") == 0) {
450     //
451     // disable all breakpoint
452     //
453     for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) {
454       Status = DebuggerBreakpointDis (DebuggerPrivate, Index);
455     }
456     EDBPrint (L"All the Breakpoint is disabled\n");
457     return EFI_DEBUG_CONTINUE;
458   }
459 
460   //
461   // Get breakpoint index
462   //
463   Index = Atoi(CommandArg);
464   if (Index == (UINTN) -1) {
465     EDBPrint (L"BreakpointDisable Argument error!\n");
466     return EFI_DEBUG_CONTINUE;
467   }
468 
469   //
470   // Disable breakpoint
471   //
472   Status = DebuggerBreakpointDis (DebuggerPrivate, Index);
473   if (EFI_ERROR(Status)) {
474     EDBPrint (L"BreakpointDisable error!\n");
475   }
476 
477   //
478   // Done
479   //
480   return EFI_DEBUG_CONTINUE;
481 }
482 
483 /**
484   DebuggerCommand - BreakpointEnable.
485 
486   @param  CommandArg        The argument for this command
487   @param  DebuggerPrivate   EBC Debugger private data structure
488   @param  ExceptionType     Exception type.
489   @param  SystemContext     EBC system context.
490 
491   @retval EFI_DEBUG_CONTINUE   formal return value
492 
493 **/
494 EFI_DEBUG_STATUS
DebuggerBreakpointEnable(IN CHAR16 * CommandArg,IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_EXCEPTION_TYPE ExceptionType,IN OUT EFI_SYSTEM_CONTEXT SystemContext)495 DebuggerBreakpointEnable (
496   IN     CHAR16                    *CommandArg,
497   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
498   IN     EFI_EXCEPTION_TYPE        ExceptionType,
499   IN OUT EFI_SYSTEM_CONTEXT        SystemContext
500   )
501 {
502   UINTN      Index;
503   EFI_STATUS Status;
504 
505   if (CommandArg == NULL) {
506     EDBPrint (L"BreakpointEnable Argument error!\n");
507     return EFI_DEBUG_CONTINUE;
508   }
509 
510   if (StriCmp (CommandArg, L"*") == 0) {
511     //
512     // enable all breakpoint
513     //
514     for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) {
515       Status = DebuggerBreakpointEn (DebuggerPrivate, Index);
516     }
517     EDBPrint (L"All the Breakpoint is enabled\n");
518     return EFI_DEBUG_CONTINUE;
519   }
520 
521   //
522   // Get breakpoint index
523   //
524   Index = Atoi(CommandArg);
525   if (Index == (UINTN) -1) {
526     EDBPrint (L"BreakpointEnable Argument error!\n");
527     return EFI_DEBUG_CONTINUE;
528   }
529 
530   //
531   // Enable breakpoint
532   //
533   Status = DebuggerBreakpointEn (DebuggerPrivate, Index);
534   if (EFI_ERROR(Status)) {
535     EDBPrint (L"BreakpointEnable error!\n");
536   }
537 
538   //
539   // Done
540   //
541   return EFI_DEBUG_CONTINUE;
542 }
543