Mercurial > pihelp
comparison main.c @ 30:320c8cc7df5a
merge
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 27 Jun 2013 00:12:01 +0800 |
parents | ce5097eacf2f |
children | 5d6a841eef82 |
comparison
equal
deleted
inserted
replaced
29:22badb6239e0 | 30:320c8cc7df5a |
---|---|
14 #include <util/crc16.h> | 14 #include <util/crc16.h> |
15 | 15 |
16 #include "hmac-sha1.h" | 16 #include "hmac-sha1.h" |
17 #include "aes.h" | 17 #include "aes.h" |
18 | 18 |
19 #include "fat.h" | |
20 #include "fat_config.h" | |
21 #include "partition.h" | |
22 #include "sd_raw.h" | |
23 #include "sd_raw_config.h" | |
24 | |
19 //#include "simple_ds18b20.h" | 25 //#include "simple_ds18b20.h" |
20 //#include "onewire.h" | 26 //#include "onewire.h" |
21 | 27 |
22 // not set via bootloader | 28 // not set via bootloader |
23 //LOCKBITS = (LB_MODE_3 & BLB0_MODE_4 & BLB1_MODE_4); | 29 //LOCKBITS = (LB_MODE_3 & BLB0_MODE_4 & BLB1_MODE_4); |
33 #define NKEYS 10 | 39 #define NKEYS 10 |
34 #define HMACLEN 20 | 40 #define HMACLEN 20 |
35 #define AESLEN 16 | 41 #define AESLEN 16 |
36 #define KEYLEN HMACLEN | 42 #define KEYLEN HMACLEN |
37 | 43 |
38 #define BAUD 38400 | 44 #define BAUD 115200 |
39 #define UBRR ((F_CPU)/(16*(BAUD))-1) | 45 #define UBRR ((F_CPU)/(16*(BAUD))-1) |
40 | 46 |
41 #define PORT_PI_BOOT PORTD | 47 #define PORT_PI_BOOT PORTD |
42 #define DDR_PI_BOOT DDRD | 48 #define DDR_PI_BOOT DDRD |
43 #define PIN_PI_BOOT PD5 | 49 #define PIN_PI_BOOT PD5 |
92 static uint32_t newboot_count; | 98 static uint32_t newboot_count; |
93 // oneshot counts down | 99 // oneshot counts down |
94 static uint32_t oneshot_count; | 100 static uint32_t oneshot_count; |
95 // countdown after the warning. | 101 // countdown after the warning. |
96 static uint8_t reboot_count; | 102 static uint8_t reboot_count; |
103 // set by adc completion interrupt | |
104 static uint8_t adc_done; | |
97 | 105 |
98 // ---- End atomic guards required | 106 // ---- End atomic guards required |
99 | 107 |
100 // boolean flags | 108 // boolean flags |
101 static uint8_t watchdog_long_hit; | 109 static uint8_t watchdog_long_hit; |
262 UDR0 = '\n'; | 270 UDR0 = '\n'; |
263 } | 271 } |
264 return (unsigned char)c; | 272 return (unsigned char)c; |
265 } | 273 } |
266 | 274 |
275 uint8_t find_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry) | |
276 { | |
277 while(fat_read_dir(dd, dir_entry)) | |
278 { | |
279 if(strcmp(dir_entry->long_name, name) == 0) | |
280 { | |
281 fat_reset_dir(dd); | |
282 return 1; | |
283 } | |
284 } | |
285 | |
286 return 0; | |
287 } | |
288 | |
289 struct fat_file_struct* | |
290 open_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name) | |
291 { | |
292 struct fat_dir_entry_struct file_entry; | |
293 if(!find_file_in_dir(fs, dd, name, &file_entry)) | |
294 return 0; | |
295 | |
296 return fat_open_file(fs, &file_entry); | |
297 } | |
298 | |
299 static void | |
300 hmac_file(const char* fn) | |
301 { | |
302 sd_raw_init(); | |
303 struct partition_struct* partition = partition_open(sd_raw_read, sd_raw_read_interval, 0, 0, 0); | |
304 struct fat_fs_struct* fs = fat_open(partition); | |
305 struct fat_dir_entry_struct directory; | |
306 fat_get_dir_entry_of_path(fs, "/", &directory); | |
307 | |
308 struct sd_raw_info disk_info; | |
309 sd_raw_get_info(&disk_info); | |
310 printf("diskinfo size %d", disk_info.capacity); | |
311 | |
312 struct fat_dir_struct* dd = fat_open_dir(fs, &directory); | |
313 struct fat_file_struct* fd = open_file_in_dir(fs, dd, "fn"); | |
314 | |
315 char c = 0; | |
316 char buf[512]; | |
317 for (int i = 0; i < 10; i++) | |
318 { | |
319 fat_read_file(fd, buf, sizeof(buf)); | |
320 c ^= buf[0]; | |
321 } | |
322 printf("total %d\n", c); | |
323 } | |
324 | |
267 static void cmd_reset() __attribute__ ((noreturn)); | 325 static void cmd_reset() __attribute__ ((noreturn)); |
268 static void | 326 static void |
269 cmd_reset() | 327 cmd_reset() |
270 { | 328 { |
271 printf_P(PSTR("reset\n")); | 329 printf_P(PSTR("reset\n")); |
582 uint16_t temp = adc_temp(); | 640 uint16_t temp = adc_temp(); |
583 // roughly? | 641 // roughly? |
584 uint16_t temp_deg = temp - 290; | 642 uint16_t temp_deg = temp - 290; |
585 printf_P(PSTR("vcc: %u mV\n" | 643 printf_P(PSTR("vcc: %u mV\n" |
586 "5v: %u mV\n" | 644 "5v: %u mV\n" |
587 "temp: %u mV (%dºC)\n"), | 645 "temp: %u mV (%dºC)\n" |
646 ), | |
588 vcc, v5, temp, temp_deg); | 647 vcc, v5, temp, temp_deg); |
589 } | 648 } |
590 | 649 |
591 void(*bootloader)() __attribute__ ((noreturn)) = (void*)0x7e00; | 650 |
592 | 651 void(*bootloader)() __attribute__ ((noreturn)) = (void*)0x7800; |
593 #if 0 | 652 |
594 #ifndef PROG_PASSWORD | 653 #ifndef PROG_PASSWORD |
595 #define PROG_PASSWORD "Y2vvjxO5" | 654 #define PROG_PASSWORD "Y2vvjxO5" |
596 #endif | 655 #endif |
597 | 656 |
598 static void | 657 static void |
623 | 682 |
624 _delay_ms(20); | 683 _delay_ms(20); |
625 | 684 |
626 bootloader(); | 685 bootloader(); |
627 } | 686 } |
628 #endif | 687 |
688 | |
689 static void | |
690 adc_sleep() | |
691 { | |
692 set_sleep_mode(SLEEP_MODE_IDLE); | |
693 sleep_mode(); | |
694 } | |
695 | |
696 #define BITSET(v, n) (((v) >> (n)) & 1) | |
697 | |
698 static inline uint8_t | |
699 popcnt(uint8_t v) | |
700 { | |
701 return BITSET(v, 0) | |
702 + BITSET(v, 1) | |
703 + BITSET(v, 2) | |
704 + BITSET(v, 3) | |
705 + BITSET(v, 4) | |
706 + BITSET(v, 5) | |
707 + BITSET(v, 6) | |
708 + BITSET(v, 7); | |
709 } | |
710 | |
711 static uint8_t | |
712 adc_bit() | |
713 { | |
714 ADCSRA |= _BV(ADSC); | |
715 loop_until_bit_is_clear(ADCSRA, ADSC); | |
716 uint8_t low = ADCL; | |
717 uint8_t high = ADCH; | |
718 return (popcnt(low)&1) ^ (popcnt(high)&1); | |
719 } | |
720 | |
721 static void | |
722 adc_random(uint8_t admux, | |
723 uint8_t *out, uint16_t num, uint32_t *tries) | |
724 { | |
725 uint8_t ret = 0; | |
726 uint8_t count = 0; | |
727 | |
728 PRR &= ~_BV(PRADC); | |
729 // /16 prescaler for 691mhz, no interrupt | |
730 ADCSRA = _BV(ADEN) | _BV(ADPS2); | |
731 | |
732 *tries = 0; | |
733 for (int i = 0; i < num; i++) | |
734 { | |
735 while (count <= 7) | |
736 { | |
737 (*tries)++; | |
738 | |
739 // Von Neumann extractor | |
740 uint8_t one = adc_bit(); | |
741 uint8_t two = adc_bit(); | |
742 if (one == two) | |
743 { | |
744 continue; | |
745 } | |
746 ret |= one << count; | |
747 count++; | |
748 } | |
749 out[i] = ret; | |
750 } | |
751 ADCSRA = 0; | |
752 PRR |= _BV(PRADC); | |
753 } | |
754 | |
755 ISR(ADC_vect) | |
756 { | |
757 adc_done = 1; | |
758 } | |
759 | |
760 static void | |
761 adc_generic(uint8_t admux, uint8_t *ret_num, uint16_t *ret_sum) | |
762 { | |
763 PRR &= ~_BV(PRADC); | |
764 | |
765 // /64 prescaler, interrupt | |
766 ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADIE); | |
767 | |
768 // set to measure 1.1 reference | |
769 ADMUX = admux; | |
770 | |
771 // delay after setting reference etc, allow settling | |
772 long_delay(300); | |
773 // average a number of samples | |
774 uint16_t sum = 0; | |
775 uint8_t num = 0; | |
776 for (uint8_t n = 0; n < 20; n++) | |
777 { | |
778 while (1) | |
779 { | |
780 adc_done = 0; | |
781 ADCSRA |= _BV(ADSC); | |
782 adc_sleep(); | |
783 | |
784 uint8_t done; | |
785 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) | |
786 { | |
787 done = adc_done; | |
788 } | |
789 if (done) | |
790 { | |
791 break; | |
792 } | |
793 } | |
794 | |
795 uint8_t low_11 = ADCL; | |
796 uint8_t high_11 = ADCH; | |
797 uint16_t val = low_11 + (high_11 << 8); | |
798 | |
799 if (n >= 4) | |
800 { | |
801 sum += val; | |
802 num++; | |
803 } | |
804 } | |
805 ADCSRA = 0; | |
806 PRR |= _BV(PRADC); | |
807 | |
808 *ret_num = num; | |
809 *ret_sum = sum; | |
810 } | |
811 | |
812 static uint16_t | |
813 adc_vcc() | |
814 { | |
815 const uint8_t mux = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); | |
816 uint16_t sum; | |
817 uint8_t num; | |
818 | |
819 adc_generic(mux, &num, &sum); | |
820 | |
821 //float res_volts = 1.1 * 1024 * num / sum; | |
822 //return 1000 * res_volts; | |
823 return ((uint32_t)1100*1024*num) / sum; | |
824 } | |
825 | |
826 #define SCALER_5V 2 | |
827 | |
828 static uint16_t | |
829 adc_5v(uint16_t vcc) | |
830 { | |
831 // set to measure ADC4 against AVCC | |
832 const uint8_t mux = _BV(REFS0) | _BV(MUX2); | |
833 uint16_t sum; | |
834 uint8_t num; | |
835 | |
836 adc_generic(mux, &num, &sum); | |
837 | |
838 return ((uint32_t)vcc*sum*SCALER_5V/(num*1024)); | |
839 } | |
840 | |
841 static uint16_t | |
842 adc_temp() | |
843 { | |
844 // set to measure temperature against 1.1v reference. | |
845 const uint8_t mux = _BV(REFS0) | _BV(REFS1) | _BV(MUX3); | |
846 uint16_t sum; | |
847 uint8_t num; | |
848 | |
849 adc_generic(mux, &num, &sum); | |
850 | |
851 // return the voltage | |
852 | |
853 return ((uint32_t)1100*sum) / (num*1024); | |
854 } | |
855 | |
856 static void | |
857 cmd_random(const char* params) | |
858 { | |
859 uint8_t admux; | |
860 uint16_t num; | |
861 uint8_t buf[100]; | |
862 | |
863 int ret = sscanf_P(params, PSTR("%hhu %u"), | |
864 &admux, &num); | |
865 if (!ret) | |
866 { | |
867 printf_P(PSTR("Bad arguments\n")); | |
868 return; | |
869 } | |
870 uint32_t tries = 0; | |
871 printf_P(PSTR("output: ")); | |
872 for (int i = 0; i < num; i+= sizeof(buf)) | |
873 { | |
874 uint32_t t; | |
875 uint16_t nr = MIN(num-i, sizeof(buf)); | |
876 adc_random(admux, buf, nr, &t); | |
877 printhex(buf, nr, stdout); | |
878 tries += t; | |
879 } | |
880 putchar('\n'); | |
881 printf_P(PSTR("%ld tries\n"), tries); | |
882 } | |
883 | |
884 | |
629 | 885 |
630 static void | 886 static void |
631 read_handler() | 887 read_handler() |
632 { | 888 { |
633 #define LOCAL_PSTR(x) const static char x ## _str[] PROGMEM = #x; | 889 #define LOCAL_PSTR(x) const static char x ## _str[] PROGMEM = #x; |
642 LOCAL_PSTR(vcc); | 898 LOCAL_PSTR(vcc); |
643 LOCAL_PSTR(reset); | 899 LOCAL_PSTR(reset); |
644 LOCAL_PSTR(newboot); | 900 LOCAL_PSTR(newboot); |
645 LOCAL_PSTR(oldboot); | 901 LOCAL_PSTR(oldboot); |
646 LOCAL_PSTR(status); | 902 LOCAL_PSTR(status); |
903 LOCAL_PSTR(random); | |
904 LOCAL_PSTR(prog); | |
647 LOCAL_HELP(set_params, "<long_limit> <short_limit> <newboot_limit>"); | 905 LOCAL_HELP(set_params, "<long_limit> <short_limit> <newboot_limit>"); |
648 LOCAL_HELP(set_key, "20_byte_hex>"); | 906 LOCAL_HELP(set_key, "20_byte_hex>"); |
649 LOCAL_HELP(oneshot, "<timeout>"); | 907 LOCAL_HELP(oneshot, "<timeout>"); |
908 LOCAL_HELP(prog, "<password>"); | |
909 LOCAL_HELP(random, "<admux> <nbytes>"); | |
650 LOCAL_HELP(hmac, "<key_index> <20_byte_hex_data>"); | 910 LOCAL_HELP(hmac, "<key_index> <20_byte_hex_data>"); |
651 LOCAL_HELP(decrypt, "<key_index> <20_byte_hmac|16_byte_aes_block>"); | 911 LOCAL_HELP(decrypt, "<key_index> <20_byte_hmac|16_byte_aes_block>"); |
652 | 912 |
653 static const struct handler { | 913 static const struct handler { |
654 PGM_P name; | 914 PGM_P name; |
664 {status_str, cmd_status, NULL}, | 924 {status_str, cmd_status, NULL}, |
665 {hmac_str, cmd_hmac, hmac_help}, | 925 {hmac_str, cmd_hmac, hmac_help}, |
666 {decrypt_str, cmd_decrypt, decrypt_help}, | 926 {decrypt_str, cmd_decrypt, decrypt_help}, |
667 {set_params_str, cmd_set_params, set_params_help}, | 927 {set_params_str, cmd_set_params, set_params_help}, |
668 {set_key_str, cmd_set_avr_key, set_key_help}, | 928 {set_key_str, cmd_set_avr_key, set_key_help}, |
929 {random_str, cmd_random, random_help}, | |
669 {vcc_str, cmd_vcc, NULL}, | 930 {vcc_str, cmd_vcc, NULL}, |
670 {reset_str, cmd_reset, NULL}, | 931 {reset_str, cmd_reset, NULL}, |
932 {prog_str, cmd_prog, prog_help}, | |
671 }; | 933 }; |
672 | 934 |
673 if (readbuf[0] == '\0') | 935 if (readbuf[0] == '\0') |
674 { | 936 { |
675 return; | 937 return; |
821 set_sleep_mode(SLEEP_MODE_IDLE); | 1083 set_sleep_mode(SLEEP_MODE_IDLE); |
822 sleep_mode(); | 1084 sleep_mode(); |
823 } | 1085 } |
824 | 1086 |
825 static void | 1087 static void |
826 adc_generic(uint8_t admux, uint8_t *ret_num, uint16_t *ret_sum) | |
827 { | |
828 PRR &= ~_BV(PRADC); | |
829 | |
830 // /16 prescaler | |
831 ADCSRA = _BV(ADEN) | _BV(ADPS2); | |
832 | |
833 // set to measure 1.1 reference | |
834 ADMUX = admux; | |
835 | |
836 // delay after setting reference etc, allow settling | |
837 long_delay(300); | |
838 // average a number of samples | |
839 uint16_t sum = 0; | |
840 uint8_t num = 0; | |
841 for (uint8_t n = 0; n < 20; n++) | |
842 { | |
843 ADCSRA |= _BV(ADSC); | |
844 loop_until_bit_is_clear(ADCSRA, ADSC); | |
845 | |
846 uint8_t low_11 = ADCL; | |
847 uint8_t high_11 = ADCH; | |
848 uint16_t val = low_11 + (high_11 << 8); | |
849 | |
850 if (n >= 4) | |
851 { | |
852 sum += val; | |
853 num++; | |
854 } | |
855 } | |
856 ADCSRA = 0; | |
857 PRR |= _BV(PRADC); | |
858 | |
859 *ret_num = num; | |
860 *ret_sum = sum; | |
861 } | |
862 | |
863 static uint16_t | |
864 adc_vcc() | |
865 { | |
866 const uint8_t mux = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); | |
867 uint16_t sum; | |
868 uint8_t num; | |
869 | |
870 adc_generic(mux, &num, &sum); | |
871 | |
872 //float res_volts = 1.1 * 1024 * num / sum; | |
873 //return 1000 * res_volts; | |
874 return ((uint32_t)1100*1024*num) / sum; | |
875 } | |
876 | |
877 #define SCALER_5V 2 | |
878 | |
879 static uint16_t | |
880 adc_5v(uint16_t vcc) | |
881 { | |
882 // set to measure ADC4 against AVCC | |
883 const uint8_t mux = _BV(REFS0) | _BV(MUX2); | |
884 uint16_t sum; | |
885 uint8_t num; | |
886 | |
887 adc_generic(mux, &num, &sum); | |
888 | |
889 return ((uint32_t)vcc*sum*SCALER_5V/(num*1024)); | |
890 } | |
891 | |
892 static uint16_t | |
893 adc_temp() | |
894 { | |
895 // set to measure temperature against 1.1v reference. | |
896 const uint8_t mux = _BV(REFS0) | _BV(REFS1) | _BV(MUX3); | |
897 uint16_t sum; | |
898 uint8_t num; | |
899 | |
900 adc_generic(mux, &num, &sum); | |
901 | |
902 // return the voltage | |
903 | |
904 return ((uint32_t)1100*sum) / (num*1024); | |
905 } | |
906 | |
907 static void | |
908 reboot_pi() | 1088 reboot_pi() |
909 { | 1089 { |
910 printf_P(PSTR("Real reboot now\n")); | 1090 printf_P(PSTR("Real reboot now\n")); |
911 // pull it low for 200ms | 1091 // pull it low for 200ms |
912 PORT_PI_RESET &= ~_BV(PIN_PI_RESET); | 1092 PORT_PI_RESET &= ~_BV(PIN_PI_RESET); |