1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
27 #include "time_support.h"
35 #include <sys/types.h>
40 /* command handlers */
41 int handle_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
42 int handle_flash_banks_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
43 int handle_flash_info_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
44 int handle_flash_probe_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
45 int handle_flash_erase_check_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
46 int handle_flash_erase_address_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
47 int handle_flash_protect_check_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
48 int handle_flash_erase_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
49 int handle_flash_write_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
50 int handle_flash_write_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
51 int handle_flash_write_image_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
52 int handle_flash_protect_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
53 int handle_flash_auto_erase_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
54 flash_bank_t
*get_flash_bank_by_addr(target_t
*target
, u32 addr
);
58 extern flash_driver_t lpc2000_flash
;
59 extern flash_driver_t cfi_flash
;
60 extern flash_driver_t at91sam7_flash
;
61 extern flash_driver_t str7x_flash
;
62 extern flash_driver_t str9x_flash
;
63 extern flash_driver_t stellaris_flash
;
64 extern flash_driver_t str9xpec_flash
;
65 extern flash_driver_t stm32x_flash
;
66 extern flash_driver_t tms470_flash
;
68 flash_driver_t
*flash_drivers
[] =
82 flash_bank_t
*flash_banks
;
83 static command_t
*flash_cmd
;
84 static int auto_erase
= 0;
86 /* wafer thin wrapper for invoking the flash driver */
87 static int flash_driver_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
90 if (bank
->target
->state
!= TARGET_HALTED
)
92 ERROR("target not halted - aborting flash write");
93 retval
=ERROR_TARGET_NOT_HALTED
;
96 retval
=bank
->driver
->write(bank
, buffer
, offset
, count
);
100 ERROR("Writing to flash bank at address 0x%08x at offset 0x%8.8x", bank
->base
, offset
);
105 static int flash_driver_erase(struct flash_bank_s
*bank
, int first
, int last
)
108 if (bank
->target
->state
!= TARGET_HALTED
)
110 ERROR("target not halted - aborting flash erase");
111 retval
=ERROR_TARGET_NOT_HALTED
;
112 } else if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
))
114 ERROR("invalid flash sector");
115 retval
=ERROR_FLASH_SECTOR_INVALID
;
118 retval
=bank
->driver
->erase(bank
, first
, last
);
120 if (retval
!=ERROR_OK
)
122 ERROR("Failed erasing banks %d to %d", first
, last
);
127 int flash_driver_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
130 if (bank
->target
->state
!= TARGET_HALTED
)
132 ERROR("target not halted - aborting flash erase");
133 retval
=ERROR_TARGET_NOT_HALTED
;
134 } else if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
))
136 ERROR("invalid flash sector");
137 retval
=ERROR_FLASH_SECTOR_INVALID
;
140 retval
=bank
->driver
->protect(bank
, set
, first
, last
);
142 if (retval
!=ERROR_OK
)
144 ERROR("Failed protecting banks %d to %d", first
, last
);
150 int flash_register_commands(struct command_context_s
*cmd_ctx
)
152 flash_cmd
= register_command(cmd_ctx
, NULL
, "flash", NULL
, COMMAND_ANY
, NULL
);
154 register_command(cmd_ctx
, flash_cmd
, "bank", handle_flash_bank_command
, COMMAND_CONFIG
, "flash_bank <driver> <base> <size> <chip_width> <bus_width> <target> [driver_options ...]");
155 register_command(cmd_ctx
, flash_cmd
, "auto_erase", handle_flash_auto_erase_command
, COMMAND_ANY
,
156 "auto erase flash sectors <on|off>");
160 int flash_init_drivers(struct command_context_s
*cmd_ctx
)
164 register_command(cmd_ctx
, flash_cmd
, "banks", handle_flash_banks_command
, COMMAND_EXEC
,
165 "list configured flash banks ");
166 register_command(cmd_ctx
, flash_cmd
, "info", handle_flash_info_command
, COMMAND_EXEC
,
167 "print info about flash bank <num>");
168 register_command(cmd_ctx
, flash_cmd
, "probe", handle_flash_probe_command
, COMMAND_EXEC
,
169 "identify flash bank <num>");
170 register_command(cmd_ctx
, flash_cmd
, "erase_check", handle_flash_erase_check_command
, COMMAND_EXEC
,
171 "check erase state of sectors in flash bank <num>");
172 register_command(cmd_ctx
, flash_cmd
, "protect_check", handle_flash_protect_check_command
, COMMAND_EXEC
,
173 "check protection state of sectors in flash bank <num>");
174 register_command(cmd_ctx
, flash_cmd
, "erase_sector", handle_flash_erase_command
, COMMAND_EXEC
,
175 "erase sectors at <bank> <first> <last>");
176 register_command(cmd_ctx
, flash_cmd
, "erase_address", handle_flash_erase_address_command
, COMMAND_EXEC
,
177 "erase address range <address> <length>");
178 register_command(cmd_ctx
, flash_cmd
, "write_bank", handle_flash_write_bank_command
, COMMAND_EXEC
,
179 "write binary data to <bank> <file> <offset>");
180 register_command(cmd_ctx
, flash_cmd
, "write_image", handle_flash_write_image_command
, COMMAND_EXEC
,
181 "write_image <file> [offset] [type]");
182 register_command(cmd_ctx
, flash_cmd
, "protect", handle_flash_protect_command
, COMMAND_EXEC
,
183 "set protection of sectors at <bank> <first> <last> <on|off>");
189 flash_bank_t
*get_flash_bank_by_num_noprobe(int num
)
194 for (p
= flash_banks
; p
; p
= p
->next
)
201 ERROR("Flash bank %d does not exist", num
);
205 flash_bank_t
*get_flash_bank_by_num(int num
)
207 flash_bank_t
*p
= get_flash_bank_by_num_noprobe(num
);
213 retval
= p
->driver
->auto_probe(p
);
215 if (retval
!= ERROR_OK
)
217 ERROR("auto_probe failed %d\n", retval
);
223 int handle_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
231 return ERROR_COMMAND_SYNTAX_ERROR
;
234 if ((target
= get_target_by_num(strtoul(args
[5], NULL
, 0))) == NULL
)
236 ERROR("target %lu not defined", strtoul(args
[5], NULL
, 0));
240 for (i
= 0; flash_drivers
[i
]; i
++)
242 if (strcmp(args
[0], flash_drivers
[i
]->name
) == 0)
246 /* register flash specific commands */
247 if (flash_drivers
[i
]->register_commands(cmd_ctx
) != ERROR_OK
)
249 ERROR("couldn't register '%s' commands", args
[0]);
253 c
= malloc(sizeof(flash_bank_t
));
255 c
->driver
= flash_drivers
[i
];
256 c
->driver_priv
= NULL
;
257 c
->base
= strtoul(args
[1], NULL
, 0);
258 c
->size
= strtoul(args
[2], NULL
, 0);
259 c
->chip_width
= strtoul(args
[3], NULL
, 0);
260 c
->bus_width
= strtoul(args
[4], NULL
, 0);
265 if (flash_drivers
[i
]->flash_bank_command(cmd_ctx
, cmd
, args
, argc
, c
) != ERROR_OK
)
267 ERROR("'%s' driver rejected flash bank at 0x%8.8x", args
[0], c
->base
);
272 /* put flash bank in linked list */
275 /* find last flash bank */
276 for (p
= flash_banks
; p
&& p
->next
; p
= p
->next
);
289 /* no matching flash driver found */
292 ERROR("flash driver '%s' not found", args
[0]);
299 int handle_flash_banks_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
306 command_print(cmd_ctx
, "no flash banks configured");
310 for (p
= flash_banks
; p
; p
= p
->next
)
312 command_print(cmd_ctx
, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i",
313 i
++, p
->driver
->name
, p
->base
, p
->size
, p
->bus_width
, p
->chip_width
);
319 int handle_flash_info_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
327 return ERROR_COMMAND_SYNTAX_ERROR
;
330 for (p
= flash_banks
; p
; p
= p
->next
, i
++)
332 if (i
== strtoul(args
[0], NULL
, 0))
336 /* attempt auto probe */
337 p
->driver
->auto_probe(p
);
339 command_print(cmd_ctx
, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i",
340 i
, p
->driver
->name
, p
->base
, p
->size
, p
->bus_width
, p
->chip_width
);
341 for (j
= 0; j
< p
->num_sectors
; j
++)
343 char *erase_state
, *protect_state
;
345 if (p
->sectors
[j
].is_erased
== 0)
346 erase_state
= "not erased";
347 else if (p
->sectors
[j
].is_erased
== 1)
348 erase_state
= "erased";
350 erase_state
= "erase state unknown";
352 if (p
->sectors
[j
].is_protected
== 0)
353 protect_state
= "not protected";
354 else if (p
->sectors
[j
].is_protected
== 1)
355 protect_state
= "protected";
357 protect_state
= "protection state unknown";
359 command_print(cmd_ctx
, "\t#%i: 0x%8.8x (0x%x %ikB) %s, %s",
360 j
, p
->sectors
[j
].offset
, p
->sectors
[j
].size
, p
->sectors
[j
].size
>>10,
361 erase_state
, protect_state
);
364 p
->driver
->info(p
, buf
, 1024);
365 command_print(cmd_ctx
, "%s", buf
);
372 int handle_flash_probe_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
379 return ERROR_COMMAND_SYNTAX_ERROR
;
382 p
= get_flash_bank_by_num_noprobe(strtoul(args
[0], NULL
, 0));
385 if ((retval
= p
->driver
->probe(p
)) == ERROR_OK
)
387 command_print(cmd_ctx
, "flash '%s' found at 0x%8.8x", p
->driver
->name
, p
->base
);
389 else if (retval
== ERROR_FLASH_BANK_INVALID
)
391 command_print(cmd_ctx
, "probing failed for flash bank '#%s' at 0x%8.8x",
396 command_print(cmd_ctx
, "unknown error when probing flash bank '#%s' at 0x%8.8x",
402 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
408 int handle_flash_erase_check_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
415 return ERROR_COMMAND_SYNTAX_ERROR
;
418 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
421 if ((retval
= p
->driver
->erase_check(p
)) == ERROR_OK
)
423 command_print(cmd_ctx
, "successfully checked erase state", p
->driver
->name
, p
->base
);
427 command_print(cmd_ctx
, "unknown error when checking erase state of flash bank #%s at 0x%8.8x",
435 int handle_flash_erase_address_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
444 target_t
*target
= get_current_target(cmd_ctx
);
448 return ERROR_COMMAND_SYNTAX_ERROR
;
451 address
= strtoul(args
[0], NULL
, 0);
452 length
= strtoul(args
[1], NULL
, 0);
455 command_print(cmd_ctx
, "Length must be >0");
456 return ERROR_COMMAND_SYNTAX_ERROR
;
459 p
= get_flash_bank_by_addr(target
, address
);
462 return ERROR_COMMAND_SYNTAX_ERROR
;
465 /* We can't know if we did a resume + halt, in which case we no longer know the erased state */
468 duration_start_measure(&duration
);
470 if ((retval
= flash_erase_address_range(target
, address
, length
)) == ERROR_OK
)
472 duration_stop_measure(&duration
, &duration_text
);
473 command_print(cmd_ctx
, "erased address 0x%8.8x length %i in %s", address
, length
, duration_text
);
480 int handle_flash_protect_check_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
487 return ERROR_COMMAND_SYNTAX_ERROR
;
490 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
493 if ((retval
= p
->driver
->protect_check(p
)) == ERROR_OK
)
495 command_print(cmd_ctx
, "successfully checked protect state");
497 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
499 command_print(cmd_ctx
, "checking protection state failed (possibly unsupported) by flash #%s at 0x%8.8x", args
[0], p
->base
);
503 command_print(cmd_ctx
, "unknown error when checking protection state of flash bank '#%s' at 0x%8.8x", args
[0], p
->base
);
508 return ERROR_COMMAND_SYNTAX_ERROR
;
514 int handle_flash_erase_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
518 int first
= strtoul(args
[1], NULL
, 0);
519 int last
= strtoul(args
[2], NULL
, 0);
521 flash_bank_t
*p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
525 duration_start_measure(&duration
);
529 return ERROR_COMMAND_SYNTAX_ERROR
;
532 if ((retval
= flash_driver_erase(p
, first
, last
)) == ERROR_OK
)
534 duration_stop_measure(&duration
, &duration_text
);
536 command_print(cmd_ctx
, "erased sectors %i through %i on flash bank %i in %s", first
, last
, strtoul(args
[0], 0, 0), duration_text
);
542 return ERROR_COMMAND_SYNTAX_ERROR
;
548 int handle_flash_protect_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
552 int first
= strtoul(args
[1], NULL
, 0);
553 int last
= strtoul(args
[2], NULL
, 0);
556 flash_bank_t
*p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
559 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
563 if (strcmp(args
[3], "on") == 0)
565 else if (strcmp(args
[3], "off") == 0)
569 return ERROR_COMMAND_SYNTAX_ERROR
;
572 retval
= flash_driver_protect(p
, set
, first
, last
);
573 if (retval
== ERROR_OK
)
575 command_print(cmd_ctx
, "%s protection for sectors %i through %i on flash bank %i", (set
) ? "set" : "cleared", first
, last
, strtoul(args
[0], 0, 0));
580 return ERROR_COMMAND_SYNTAX_ERROR
;
587 int handle_flash_write_image_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
589 target_t
*target
= get_current_target(cmd_ctx
);
601 return ERROR_COMMAND_SYNTAX_ERROR
;
607 ERROR("no target selected");
611 duration_start_measure(&duration
);
615 image
.base_address_set
= 1;
616 image
.base_address
= strtoul(args
[1], NULL
, 0);
620 image
.base_address_set
= 0;
621 image
.base_address
= 0x0;
624 image
.start_address_set
= 0;
626 retval
= image_open(&image
, args
[0], (argc
== 3) ? args
[2] : NULL
);
627 if (retval
!= ERROR_OK
)
629 command_print(cmd_ctx
, "image_open error: %s", image
.error_str
);
633 retval
= flash_write(target
, &image
, &written
, auto_erase
);
635 if (retval
!= ERROR_OK
)
641 duration_stop_measure(&duration
, &duration_text
);
642 if (retval
== ERROR_OK
)
644 command_print(cmd_ctx
, "wrote %u byte from file %s in %s (%f kb/s)",
645 written
, args
[0], duration_text
,
646 (float)written
/ 1024.0 / ((float)duration
.duration
.tv_sec
+ ((float)duration
.duration
.tv_usec
/ 1000000.0)));
655 int handle_flash_write_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
671 return ERROR_COMMAND_SYNTAX_ERROR
;
674 duration_start_measure(&duration
);
676 offset
= strtoul(args
[2], NULL
, 0);
677 p
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
680 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
684 if (fileio_open(&fileio
, args
[1], FILEIO_READ
, FILEIO_BINARY
) != ERROR_OK
)
686 command_print(cmd_ctx
, "flash write_binary error: %s", fileio
.error_str
);
690 buffer
= malloc(fileio
.size
);
691 if (fileio_read(&fileio
, fileio
.size
, buffer
, &buf_cnt
) != ERROR_OK
)
693 command_print(cmd_ctx
, "flash write_binary error: %s", fileio
.error_str
);
697 retval
= flash_driver_write(p
, buffer
, offset
, buf_cnt
);
701 duration_stop_measure(&duration
, &duration_text
);
702 if (retval
!=ERROR_OK
)
704 command_print(cmd_ctx
, "wrote %"PRIi64
" byte from file %s to flash bank %i at offset 0x%8.8x in %s (%f kb/s)",
705 fileio
.size
, args
[1], strtoul(args
[0], NULL
, 0), offset
, duration_text
,
706 (float)fileio
.size
/ 1024.0 / ((float)duration
.duration
.tv_sec
+ ((float)duration
.duration
.tv_usec
/ 1000000.0)));
710 fileio_close(&fileio
);
715 void flash_set_dirty(void)
720 /* set all flash to require erasing */
721 for (c
= flash_banks
; c
; c
= c
->next
)
723 for (i
= 0; i
< c
->num_sectors
; i
++)
725 c
->sectors
[i
].is_erased
= 0;
730 /* lookup flash bank by address */
731 flash_bank_t
*get_flash_bank_by_addr(target_t
*target
, u32 addr
)
735 /* cycle through bank list */
736 for (c
= flash_banks
; c
; c
= c
->next
)
739 retval
= c
->driver
->auto_probe(c
);
741 if (retval
!= ERROR_OK
)
743 ERROR("auto_probe failed %d\n", retval
);
746 /* check whether address belongs to this flash bank */
747 if ((addr
>= c
->base
) && (addr
< c
->base
+ c
->size
) && target
== c
->target
)
750 ERROR("No flash at address 0x%08x\n", addr
);
754 /* erase given flash region, selects proper bank according to target and address */
755 int flash_erase_address_range(target_t
*target
, u32 addr
, u32 length
)
762 if ((c
= get_flash_bank_by_addr(target
, addr
)) == NULL
)
763 return ERROR_FLASH_DST_OUT_OF_BANK
; /* no corresponding bank found */
765 if (c
->size
== 0 || c
->num_sectors
== 0)
766 return ERROR_FLASH_BANK_INVALID
;
770 /* special case, erase whole bank when length is zero */
772 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
774 return flash_driver_erase(c
, 0, c
->num_sectors
- 1);
777 /* check whether it fits */
778 if (addr
+ length
> c
->base
+ c
->size
)
779 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
783 for (i
= 0; i
< c
->num_sectors
; i
++)
785 /* check whether sector overlaps with the given range and is not yet erased */
786 if (addr
< c
->sectors
[i
].offset
+ c
->sectors
[i
].size
&& addr
+ length
> c
->sectors
[i
].offset
&& c
->sectors
[i
].is_erased
!= 1) {
787 /* if first is not set yet then this is the first sector */
790 last
= i
; /* and it is the last one so far in any case */
794 if( first
== -1 || last
== -1 )
797 return flash_driver_erase(c
, first
, last
);
800 /* write (optional verify) an image to flash memory of the given target */
801 int flash_write(target_t
*target
, image_t
*image
, u32
*written
, int erase
)
817 /* assume all sectors need erasing - stops any problems
818 * when flash_write is called multiple times */
823 /* loop until we reach end of the image */
824 while (section
< image
->num_sections
)
830 u32 run_address
= image
->sections
[section
].base_address
+ section_offset
;
831 u32 run_size
= image
->sections
[section
].size
- section_offset
;
833 if (image
->sections
[section
].size
== 0)
835 WARNING("empty section %d", section
);
841 /* find the corresponding flash bank */
842 if ((c
= get_flash_bank_by_addr(target
, run_address
)) == NULL
)
844 section
++; /* and skip it */
849 /* collect consecutive sections which fall into the same bank */
850 section_first
= section
;
851 section_last
= section
;
852 while ((run_address
+ run_size
< c
->base
+ c
->size
)
853 && (section_last
+ 1 < image
->num_sections
))
855 if (image
->sections
[section_last
+ 1].base_address
< (run_address
+ run_size
))
857 DEBUG("section %d out of order(very slightly surprising, but supported)", section_last
+ 1);
860 if (image
->sections
[section_last
+ 1].base_address
!= (run_address
+ run_size
))
862 run_size
+= image
->sections
[++section_last
].size
;
865 /* fit the run into bank constraints */
866 if (run_address
+ run_size
> c
->base
+ c
->size
)
867 run_size
= c
->base
+ c
->size
- run_address
;
869 /* allocate buffer */
870 buffer
= malloc(run_size
);
873 /* read sections to the buffer */
874 while (buffer_size
< run_size
)
878 if (buffer_size
- run_size
<= image
->sections
[section
].size
- section_offset
)
879 size_read
= buffer_size
- run_size
;
881 size_read
= image
->sections
[section
].size
- section_offset
;
883 if ((retval
= image_read_section(image
, section
, section_offset
,
884 size_read
, buffer
+ buffer_size
, &size_read
)) != ERROR_OK
|| size_read
== 0)
891 buffer_size
+= size_read
;
892 section_offset
+= size_read
;
894 if (section_offset
>= image
->sections
[section
].size
)
905 /* calculate and erase sectors */
906 retval
= flash_erase_address_range( target
, run_address
, run_size
);
909 if (retval
== ERROR_OK
)
911 /* write flash sectors */
912 retval
= flash_driver_write(c
, buffer
, run_address
- c
->base
, run_size
);
917 if (retval
!= ERROR_OK
)
919 return retval
; /* abort operation */
923 *written
+= run_size
; /* add run size to total written counter */
929 int handle_flash_auto_erase_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
933 return ERROR_COMMAND_SYNTAX_ERROR
;
937 if (strcmp(args
[0], "on") == 0)
939 else if (strcmp(args
[0], "off") == 0)
942 return ERROR_COMMAND_SYNTAX_ERROR
;
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)