]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - armsrc/util.c
Implement version information storage and retrieval for the bootrom and the osimage.
[proxmark3-svn] / armsrc / util.c
index b3f0e76e4df5b5127e68042e26f45899b4633231..650ba22bacb31914c142ffeee9a0a882c940fb3b 100644 (file)
@@ -51,3 +51,221 @@ int strlen(char *str)
        }\r
        return l;\r
 }\r
+\r
+char* strncat(char *dest, const char *src, unsigned int n)\r
+{\r
+       unsigned int dest_len = strlen(dest);\r
+       unsigned int i;\r
+       \r
+       for (i = 0 ; i < n && src[i] != '\0' ; i++)\r
+               dest[dest_len + i] = src[i];\r
+       dest[dest_len + i] = '\0';\r
+       \r
+       return dest;\r
+}\r
+\r
+\r
+void LEDsoff()\r
+{\r
+       LED_A_OFF();\r
+       LED_B_OFF();\r
+       LED_C_OFF();\r
+       LED_D_OFF();\r
+}\r
+\r
+// LEDs: R(C) O(A) G(B) -- R(D) [1, 2, 4 and 8]\r
+void LED(int led, int ms)\r
+{\r
+       if (led & LED_RED)\r
+               LED_C_ON();\r
+       if (led & LED_ORANGE)\r
+               LED_A_ON();\r
+       if (led & LED_GREEN)\r
+               LED_B_ON();\r
+       if (led & LED_RED2)\r
+               LED_D_ON();\r
+\r
+       if (!ms)\r
+               return;\r
+\r
+       SpinDelay(ms);\r
+\r
+       if (led & LED_RED)\r
+               LED_C_OFF();\r
+       if (led & LED_ORANGE)\r
+               LED_A_OFF();\r
+       if (led & LED_GREEN)\r
+               LED_B_OFF();\r
+       if (led & LED_RED2)\r
+               LED_D_OFF();\r
+}\r
+\r
+\r
+// Determine if a button is double clicked, single clicked,\r
+// not clicked, or held down (for ms || 1sec)\r
+// In general, don't use this function unless you expect a\r
+// double click, otherwise it will waste 500ms -- use BUTTON_HELD instead\r
+int BUTTON_CLICKED(int ms)\r
+{\r
+       // Up to 500ms in between clicks to mean a double click\r
+       int ticks = (48000 * (ms ? ms : 1000)) >> 10;\r
+\r
+       // If we're not even pressed, forget about it!\r
+       if (!BUTTON_PRESS())\r
+               return BUTTON_NO_CLICK;\r
+\r
+       // Borrow a PWM unit for my real-time clock\r
+       PWM_ENABLE = PWM_CHANNEL(0);\r
+       // 48 MHz / 1024 gives 46.875 kHz\r
+       PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);\r
+       PWM_CH_DUTY_CYCLE(0) = 0;\r
+       PWM_CH_PERIOD(0) = 0xffff;\r
+\r
+       WORD start = (WORD)PWM_CH_COUNTER(0);\r
+\r
+       int letoff = 0;\r
+       for(;;)\r
+       {\r
+               WORD now = (WORD)PWM_CH_COUNTER(0);\r
+\r
+               // We haven't let off the button yet\r
+               if (!letoff)\r
+               {\r
+                       // We just let it off!\r
+                       if (!BUTTON_PRESS())\r
+                       {\r
+                               letoff = 1;\r
+\r
+                               // reset our timer for 500ms\r
+                               start = (WORD)PWM_CH_COUNTER(0);\r
+                               ticks = (48000 * (500)) >> 10;\r
+                       }\r
+\r
+                       // Still haven't let it off\r
+                       else\r
+                               // Have we held down a full second?\r
+                               if (now == (WORD)(start + ticks))\r
+                                       return BUTTON_HOLD;\r
+               }\r
+\r
+               // We already let off, did we click again?\r
+               else\r
+                       // Sweet, double click!\r
+                       if (BUTTON_PRESS())\r
+                               return BUTTON_DOUBLE_CLICK;\r
+\r
+                       // Have we ran out of time to double click?\r
+                       else\r
+                               if (now == (WORD)(start + ticks))\r
+                                       // At least we did a single click\r
+                                       return BUTTON_SINGLE_CLICK;\r
+\r
+               WDT_HIT();\r
+       }\r
+\r
+       // We should never get here\r
+       return BUTTON_ERROR;\r
+}\r
+\r
+// Determine if a button is held down\r
+int BUTTON_HELD(int ms)\r
+{\r
+       // If button is held for one second\r
+       int ticks = (48000 * (ms ? ms : 1000)) >> 10;\r
+\r
+       // If we're not even pressed, forget about it!\r
+       if (!BUTTON_PRESS())\r
+               return BUTTON_NO_CLICK;\r
+\r
+       // Borrow a PWM unit for my real-time clock\r
+       PWM_ENABLE = PWM_CHANNEL(0);\r
+       // 48 MHz / 1024 gives 46.875 kHz\r
+       PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);\r
+       PWM_CH_DUTY_CYCLE(0) = 0;\r
+       PWM_CH_PERIOD(0) = 0xffff;\r
+\r
+       WORD start = (WORD)PWM_CH_COUNTER(0);\r
+\r
+       for(;;)\r
+       {\r
+               WORD now = (WORD)PWM_CH_COUNTER(0);\r
+\r
+               // As soon as our button let go, we didn't hold long enough\r
+               if (!BUTTON_PRESS())\r
+                       return BUTTON_SINGLE_CLICK;\r
+\r
+               // Have we waited the full second?\r
+               else\r
+                       if (now == (WORD)(start + ticks))\r
+                               return BUTTON_HOLD;\r
+\r
+               WDT_HIT();\r
+       }\r
+\r
+       // We should never get here\r
+       return BUTTON_ERROR;\r
+}\r
+\r
+// attempt at high resolution microsecond timer\r
+// beware: timer counts in 21.3uS increments (1024/48Mhz)\r
+void SpinDelayUs(int us)\r
+{\r
+       int ticks = (48*us) >> 10;\r
+\r
+       // Borrow a PWM unit for my real-time clock\r
+       PWM_ENABLE = PWM_CHANNEL(0);\r
+       // 48 MHz / 1024 gives 46.875 kHz\r
+       PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);\r
+       PWM_CH_DUTY_CYCLE(0) = 0;\r
+       PWM_CH_PERIOD(0) = 0xffff;\r
+\r
+       WORD start = (WORD)PWM_CH_COUNTER(0);\r
+\r
+       for(;;) {\r
+               WORD now = (WORD)PWM_CH_COUNTER(0);\r
+               if (now == (WORD)(start + ticks))\r
+                       return;\r
+\r
+               WDT_HIT();\r
+       }\r
+}\r
+\r
+void SpinDelay(int ms)\r
+{\r
+  // convert to uS and call microsecond delay function\r
+       SpinDelayUs(ms*1000);\r
+}\r
+\r
+/* Similar to FpgaGatherVersion this formats stored version information\r
+ * into a string representation. It takes a pointer to the struct version_information,\r
+ * verifies the magic properties, then stores a formatted string, prefixed by\r
+ * prefix in dst.
+ */\r
+void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information)\r
+{\r
+       struct version_information *v = (struct version_information*)version_information;\r
+       dst[0] = 0;\r
+       strncat(dst, prefix, len);\r
+       if(v->magic != VERSION_INFORMATION_MAGIC) {\r
+               strncat(dst, "Missing/Invalid version information", len);\r
+               return;\r
+       }\r
+       if(v->versionversion != 1) {\r
+               strncat(dst, "Version information not understood", len);\r
+               return;\r
+       }\r
+       if(!v->present) {\r
+               strncat(dst, "Version information not available", len);\r
+               return;\r
+       }\r
+       \r
+       strncat(dst, v->svnversion, len);\r
+       if(v->clean == 0) {\r
+               strncat(dst, "-unclean", len);\r
+       } else if(v->clean == 2) {\r
+               strncat(dst, "-suspect", len);\r
+       }\r
+       \r
+       strncat(dst, " ", len);\r
+       strncat(dst, v->buildtime, len);\r
+}\r
Impressum, Datenschutz