Pavel Chromy: memory leak in at91sam7 flash driver, possible incorrect pointer conver...
authoroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Wed, 5 Mar 2008 13:27:50 +0000 (13:27 +0000)
committeroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Wed, 5 Mar 2008 13:27:50 +0000 (13:27 +0000)
uninitialized buffer issue in handle_flash_info_command in flash.c, some formatting.

git-svn-id: svn://svn.berlios.de/openocd/trunk@446 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/flash/at91sam7.c
src/flash/at91sam7.h
src/flash/flash.c
src/flash/flash.h
src/flash/stellaris.c

index 99a8a9af9b74215d4b585c48c97f9a0b4d3c1d27..0c7a7c0a378358a4e2bb6ea3d8c019bea4589480 100644 (file)
@@ -77,7 +77,7 @@ flash_driver_t at91sam7_flash =
        .protect = at91sam7_protect,
        .write = at91sam7_write,
        .probe = at91sam7_probe,
-       .auto_probe = at91sam7_auto_probe,
+       .auto_probe = at91sam7_probe,
        .erase_check = at91sam7_erase_check,
        .protect_check = at91sam7_protect_check,
        .info = at91sam7_info
@@ -145,7 +145,7 @@ u32 at91sam7_get_flash_status(flash_bank_t *bank, u8 flashplane)
        return fsr;
 }
 
-/** Read clock configuration and set at91sam7_info->usec_clocks*/ 
+/* Read clock configuration and set at91sam7_info->usec_clocks*/
 void at91sam7_read_clock_info(flash_bank_t *bank)
 {
        at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
@@ -180,7 +180,7 @@ void at91sam7_read_clock_info(flash_bank_t *bank)
 
                case 2:                 /* Reserved */
                        break;
-               case 3:         /* PLL Clock */
+               case 3:                 /* PLL Clock */
                        if (mcfr & CKGR_MCFR_MAINRDY) 
                        {
                                target_read_u32(target, CKGR_PLLR, &pllr);
@@ -313,6 +313,9 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
        target_t *target = bank->target;
        u32 cidr, status;
        int sectornum;
+
+       if (at91sam7_info->cidr != 0)
+               return ERROR_OK; /* already probed, multiple probes may cause memory leak, not allowed */
        
        /* Read and parse chip identification register */
        target_read_u32(target, DBGU_CIDR, &cidr);
@@ -553,9 +556,8 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
                return ERROR_OK;
        }
        
-   WARNING("at91sam7 flash only tested for AT91SAM7Sxx series");
-       
-   return ERROR_OK;
+       WARNING("at91sam7 flash only tested for AT91SAM7Sxx series");
+       return ERROR_OK;
 }
 
 int at91sam7_erase_check(struct flash_bank_s *bank)
@@ -579,20 +581,14 @@ int at91sam7_protect_check(struct flash_bank_s *bank)
        
        at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
 
-       if (bank->target->state != TARGET_HALTED)
-       {
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
        if (at91sam7_info->cidr == 0)
        {
-               at91sam7_read_part_info(bank);
+               return ERROR_FLASH_BANK_NOT_PROBED;
        }
 
-       if (at91sam7_info->cidr == 0)
+       if (bank->target->state != TARGET_HALTED)
        {
-               WARNING("Cannot identify target as an AT91SAM");
-               return ERROR_FLASH_OPERATION_FAILED;
+               return ERROR_TARGET_NOT_HALTED;
        }
 
        for (flashplane=0;flashplane<at91sam7_info->num_planes;flashplane++)
@@ -619,7 +615,6 @@ int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, ch
        
        at91sam7_info = malloc(sizeof(at91sam7_flash_bank_t));
        bank->driver_priv = at91sam7_info;
-       at91sam7_info->probed = 0;
        
        /* part wasn't probed for info yet */
        at91sam7_info->cidr = 0;
@@ -634,21 +629,15 @@ int at91sam7_erase(struct flash_bank_s *bank, int first, int last)
        at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
        u8 flashplane;
 
-       if (bank->target->state != TARGET_HALTED)
-       {
-               return ERROR_TARGET_NOT_HALTED;
-       }
-       
        if (at91sam7_info->cidr == 0)
        {
-               at91sam7_read_part_info(bank);
+               return ERROR_FLASH_BANK_NOT_PROBED;
        }
 
-       if (at91sam7_info->cidr == 0)
+       if (bank->target->state != TARGET_HALTED)
        {
-               WARNING("Cannot identify target as an AT91SAM");
-               return ERROR_FLASH_OPERATION_FAILED;
-       }       
+               return ERROR_TARGET_NOT_HALTED;
+       }
        
        if ((first < 0) || (last < first) || (last >= bank->num_sectors))
        {
@@ -683,6 +672,11 @@ int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last)
        
        at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
        
+       if (at91sam7_info->cidr == 0)
+       {
+               return ERROR_FLASH_BANK_NOT_PROBED;
+       }
+
        if (bank->target->state != TARGET_HALTED)
        {
                return ERROR_TARGET_NOT_HALTED;
@@ -693,17 +687,6 @@ int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last)
                return ERROR_FLASH_SECTOR_INVALID;
        }
        
-       if (at91sam7_info->cidr == 0)
-       {
-               at91sam7_read_part_info(bank);
-       }
-
-       if (at91sam7_info->cidr == 0)
-       {
-               WARNING("Cannot identify target as an AT91SAM");
-               return ERROR_FLASH_OPERATION_FAILED;
-       }
-       
        at91sam7_read_clock_info(bank); 
        
        for (lockregion=first;lockregion<=last;lockregion++) 
@@ -738,22 +721,16 @@ int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
        u32 first_page, last_page, pagen, buffer_pos;
        u8 flashplane;
        
-       if (bank->target->state != TARGET_HALTED)
-       {
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
        if (at91sam7_info->cidr == 0)
        {
-               at91sam7_read_part_info(bank);
+               return ERROR_FLASH_BANK_NOT_PROBED;
        }
 
-       if (at91sam7_info->cidr == 0)
+       if (bank->target->state != TARGET_HALTED)
        {
-               WARNING("Cannot identify target as an AT91SAM");
-               return ERROR_FLASH_OPERATION_FAILED;
+               return ERROR_TARGET_NOT_HALTED;
        }
-       
+
        if (offset + count > bank->size)
                return ERROR_FLASH_DST_OUT_OF_BANK;
        
@@ -809,56 +786,34 @@ int at91sam7_probe(struct flash_bank_s *bank)
         * if this is an at91sam7, it has the configured flash
         */
        at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
-       at91sam7_info->probed = 0;
+       int retval;
        
-       if (bank->target->state != TARGET_HALTED)
+       if (at91sam7_info->cidr != 0)
        {
-               return ERROR_TARGET_NOT_HALTED;
+               return ERROR_OK; /* already probed */
        }
 
-       if (at91sam7_info->cidr == 0)
+       if (bank->target->state != TARGET_HALTED)
        {
-               at91sam7_read_part_info(bank);
+               return ERROR_TARGET_NOT_HALTED;
        }
 
-       if (at91sam7_info->cidr == 0)
-       {
-               WARNING("Cannot identify target as an AT91SAM");
-               return ERROR_FLASH_OPERATION_FAILED;
-       }
-       
-       at91sam7_info->probed = 1;
+       retval = at91sam7_read_part_info(bank);
+       if (retval != ERROR_OK)
+               return retval;
        
        return ERROR_OK;
 }
 
 
-int at91sam7_auto_probe(struct flash_bank_s *bank)
-{
-       at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
-       if (at91sam7_info->probed)
-               return ERROR_OK;
-       return at91sam7_probe(bank);
-}
-
 int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size)
 {
        int printed, flashplane;
        at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
        
-       if (bank->target->state != TARGET_HALTED)
-       {
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
-       at91sam7_read_part_info(bank);
-
        if (at91sam7_info->cidr == 0)
        {
-               printed = snprintf(buf, buf_size, "Cannot identify target as an AT91SAM\n");
-               buf += printed;
-               buf_size -= printed;
-               return ERROR_FLASH_OPERATION_FAILED;
+               return ERROR_FLASH_BANK_NOT_PROBED;
        }
        
        printed = snprintf(buf, buf_size, "\nat91sam7 information: Chip is %s\n",at91sam7_info->target_name);
@@ -894,7 +849,7 @@ int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size)
                buf_size -= printed;
        }
                        
-       printed = snprintf(buf, buf_size, "securitybit: %i, nvmbits: 0x%1.1x\n", at91sam7_info->securitybit, at91sam7_info->nvmbits);
+       printed = snprintf(buf, buf_size, "securitybit: %i,  nvmbits(%i): 0x%1.1x\n", at91sam7_info->securitybit, at91sam7_info->num_nvmbits, at91sam7_info->nvmbits);
        buf += printed;
        buf_size -= printed;
 
@@ -919,6 +874,7 @@ int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd,
        u32 status;
        char *value;
        at91sam7_flash_bank_t *at91sam7_info;
+       int retval;
 
        if (argc < 3)
        {
@@ -926,32 +882,48 @@ int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd,
                return ERROR_OK;
        }
        
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       bank = get_flash_bank_by_num_noprobe(strtoul(args[0], NULL, 0));
        bit = atoi(args[1]);
        value = args[2];
 
-       if (!bank)
+       if (bank ==  NULL)
        {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       if (bank->driver != &at91sam7_flash)
+       {
+               command_print(cmd_ctx, "not an at91sam7 flash bank '%s'", args[0]);
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       if (strcmp(value, "set") == 0)
+       {
+               flashcmd = SGPB;
+       }
+       else if (strcmp(value, "clear") == 0)
+       {
+               flashcmd = CGPB;
+       }
+       else
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        at91sam7_info = bank->driver_priv;
 
        if (bank->target->state != TARGET_HALTED)
        {
+               ERROR("target has to be halted to perform flash operation");
                return ERROR_TARGET_NOT_HALTED;
        }
        
        if (at91sam7_info->cidr == 0)
        {
-               at91sam7_read_part_info(bank);
-       }
-
-       if (at91sam7_info->cidr == 0)
-       {
-               WARNING("Cannot identify target as an AT91SAM");
-               return ERROR_FLASH_OPERATION_FAILED;
+               retval = at91sam7_read_part_info(bank);
+               if (retval != ERROR_OK) {
+                       return retval;
+               }
        }
 
        if ((bit<0) || (at91sam7_info->num_nvmbits <= bit))
@@ -960,19 +932,6 @@ int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd,
                return ERROR_OK;
        }
 
-       if (strcmp(value, "set") == 0)
-       {
-               flashcmd = SGPB;
-       }
-       else if (strcmp(value, "clear") == 0)
-       {
-               flashcmd = CGPB;
-       }
-       else
-       {
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
        /* Configure the flash controller timing */
        at91sam7_read_clock_info(bank); 
        at91sam7_set_flash_mode(bank, 0, FMR_TIMING_NVBITS);
index eb0213c035e86e8611eb8020e1c7c8558af0abfb..ecb5670145328e9cdb739ec9c5e6cb48e1fd9e20 100644 (file)
@@ -59,9 +59,7 @@ typedef struct at91sam7_flash_bank_s
        /* main clock status */
        u8  mck_valid;
        u32 mck_freq;
-       
-       int probed;
-       
+
 } at91sam7_flash_bank_t;
 
 /* AT91SAM7 control registers */
index 92ac6fd6c315c1ee918fb5a2179bec0909557611..1c6773dbbcbdb93ac5f61e1088b676974d8cd7e5 100644 (file)
@@ -93,7 +93,7 @@ static int flash_driver_write(struct flash_bank_s *bank, u8 *buffer, u32 offset,
        retval=bank->driver->write(bank, buffer, offset, count);
        if (retval!=ERROR_OK)
        {
-               ERROR("error writing to flash at address 0x%08x at offset 0x%8.8x", bank->base, offset);
+               ERROR("error writing to flash at address 0x%08x at offset 0x%8.8x (%d)", bank->base, offset, retval);
        }
 
        return retval;
@@ -106,7 +106,7 @@ static int flash_driver_erase(struct flash_bank_s *bank, int first, int last)
        retval=bank->driver->erase(bank, first, last);
        if (retval!=ERROR_OK)
        {
-               ERROR("failed erasing sectors %d to %d", first, last);
+               ERROR("failed erasing sectors %d to %d (%d)", first, last, retval);
        }
 
        return retval;
@@ -119,7 +119,7 @@ int flash_driver_protect(struct flash_bank_s *bank, int set, int first, int last
        retval=bank->driver->protect(bank, set, first, last);
        if (retval!=ERROR_OK)
        {
-               ERROR("failed setting protection for areas %d to %d", first, last);
+               ERROR("failed setting protection for areas %d to %d (%d)", first, last, retval);
        }
 
        return retval;
@@ -311,6 +311,7 @@ int handle_flash_info_command(struct command_context_s *cmd_ctx, char *cmd, char
        flash_bank_t *p;
        int i = 0;
        int j = 0;
+       int retval;
 
        if (argc != 1)
        {
@@ -351,8 +352,11 @@ int handle_flash_info_command(struct command_context_s *cmd_ctx, char *cmd, char
                                                        erase_state, protect_state);
                        }
 
-                       p->driver->info(p, buf, 1024);
+                       *buf = '\0'; /* initialize buffer, otherwise it migh contain garbage if driver function fails */
+                       retval = p->driver->info(p, buf, sizeof(buf));
                        command_print(cmd_ctx, "%s", buf);
+                       if (retval != ERROR_OK)
+                               ERROR("error retrieving flash info (%d)", retval);
                }
        }
 
@@ -918,7 +922,6 @@ int handle_flash_auto_erase_command(struct command_context_s *cmd_ctx, char *cmd
        if (argc != 1)
        {
                return ERROR_COMMAND_SYNTAX_ERROR;
-
        }
 
        if (strcmp(args[0], "on") == 0)
index 2e6c1ec0949a9736f729efd1516784c62aa39239..846ddc4b196c07aef5795244744f5f416cd20e85 100644 (file)
@@ -80,6 +80,7 @@ extern void flash_set_dirty(void);
 extern int flash_get_bank_count();
 
 extern flash_bank_t *get_flash_bank_by_num(int num);
+extern flash_bank_t *get_flash_bank_by_num_noprobe(int num);
 extern flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr);
 
 #define                ERROR_FLASH_BANK_INVALID                (-900)
index 2eca290cb7ce34a35bd871a4f65a0ae49392c354..2f91e564e2d6d4f1138f7338efc18e4e342a84ac 100644 (file)
@@ -77,7 +77,7 @@ flash_driver_t stellaris_flash =
 
 struct {
        u32 partno;
-    char *partname;
+       char *partname;
 }      StellarisParts[] =
 {
        {0x01,"LM3S101"},
@@ -269,9 +269,9 @@ int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size)
        {
                device_class = 0;
        }       
-    printed = snprintf(buf, buf_size, "\nLMI Stellaris information: Chip is class %i(%s) %s v%c.%i\n",
-         device_class, StellarisClassname[device_class], stellaris_info->target_name,
-         'A' + (stellaris_info->did0>>8)&0xFF, (stellaris_info->did0)&0xFF);
+       printed = snprintf(buf, buf_size, "\nLMI Stellaris information: Chip is class %i(%s) %s v%c.%i\n",
+         device_class, StellarisClassname[device_class], stellaris_info->target_name,
+         'A' + (stellaris_info->did0>>8)&0xFF, (stellaris_info->did0)&0xFF);
        buf += printed;
        buf_size -= printed;
 
@@ -352,7 +352,7 @@ void stellaris_read_clock_info(flash_bank_t *bank)
                stellaris_info->mck_freq = mainfreq;
        
        /* Forget old flash timing */
-       stellaris_set_flash_mode(bank,0);
+       stellaris_set_flash_mode(bank,0);
 }
 
 /* Setup the timimg registers */
@@ -407,7 +407,7 @@ int stellaris_read_part_info(struct flash_bank_s *bank)
 {
        stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
        target_t *target = bank->target;
-    u32 did0,did1, ver, fam, status;
+       u32 did0,did1, ver, fam, status;
        int i;
        
        /* Read and parse chip identification register */
@@ -417,10 +417,10 @@ int stellaris_read_part_info(struct flash_bank_s *bank)
        target_read_u32(target, SCB_BASE|DC1, &stellaris_info->dc1);
        DEBUG("did0 0x%x, did1 0x%x, dc0 0x%x, dc1 0x%x",did0, did1, stellaris_info->dc0,stellaris_info->dc1);
 
-    ver = did0 >> 28;
-    if((ver != 0) && (ver != 1))
+       ver = did0 >> 28;
+       if((ver != 0) && (ver != 1))
        {
-        WARNING("Unknown did0 version, cannot identify target");
+               WARNING("Unknown did0 version, cannot identify target");
                return ERROR_FLASH_OPERATION_FAILED;    
        }
 
@@ -430,11 +430,11 @@ int stellaris_read_part_info(struct flash_bank_s *bank)
                return ERROR_FLASH_OPERATION_FAILED;
        }
 
-    ver = did1 >> 28;
-    fam = (did1 >> 24) & 0xF;
-    if(((ver != 0) && (ver != 1)) || (fam != 0))
+       ver = did1 >> 28;
+       fam = (did1 >> 24) & 0xF;
+       if(((ver != 0) && (ver != 1)) || (fam != 0))
        {
-        WARNING("Unknown did1 version/family, cannot positively identify target as a Stellaris");
+               WARNING("Unknown did1 version/family, cannot positively identify target as a Stellaris");
        }
 
        for (i=0;StellarisParts[i].partno;i++)
@@ -464,7 +464,7 @@ int stellaris_read_part_info(struct flash_bank_s *bank)
 }
 
 /***************************************************************************
-*      flash operations                                         *
+*      flash operations                                                       *
 ***************************************************************************/
 
 int stellaris_erase_check(struct flash_bank_s *bank)
@@ -527,7 +527,7 @@ int stellaris_erase(struct flash_bank_s *bank, int first, int last)
 
        if (stellaris_info->did1 == 0)
        {
-        WARNING("Cannot identify target as Stellaris");
+               WARNING("Cannot identify target as Stellaris");
                return ERROR_FLASH_OPERATION_FAILED;
        }       
        
@@ -546,7 +546,7 @@ int stellaris_erase(struct flash_bank_s *bank, int first, int last)
 
        if ((first == 0) && (last == (stellaris_info->num_pages-1)))
        {
-        target_write_u32(target, FLASH_FMA, 0);
+               target_write_u32(target, FLASH_FMA, 0);
                target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
                /* Wait until erase complete */
                do
@@ -555,18 +555,18 @@ int stellaris_erase(struct flash_bank_s *bank, int first, int last)
                }
                while(flash_fmc & FMC_MERASE);
                
-        /* if device has > 128k, then second erase cycle is needed */
-        if(stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
-        {
-            target_write_u32(target, FLASH_FMA, 0x20000);
-            target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
-            /* Wait until erase complete */
-            do
-            {
-                target_read_u32(target, FLASH_FMC, &flash_fmc);
-            }
-            while(flash_fmc & FMC_MERASE);
-        }
+               /* if device has > 128k, then second erase cycle is needed */
+               if(stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
+               {
+                       target_write_u32(target, FLASH_FMA, 0x20000);
+                       target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
+                       /* Wait until erase complete */
+                       do
+                       {
+                               target_read_u32(target, FLASH_FMC, &flash_fmc);
+                       }
+                       while(flash_fmc & FMC_MERASE);
+               }
 
                return ERROR_OK;
        }
@@ -687,26 +687,26 @@ u8 stellaris_write_code[] =
        r6 = bytes written
        r7 = temp reg
 */
-       0x07,0x4B,              /* ldr r3,pFLASH_CTRL_BASE */
-       0x08,0x4C,              /* ldr r4,FLASHWRITECMD */
-       0x01,0x25,              /* movs r5, 1 */
-       0x00,0x26,              /* movs r6, #0 */
+       0x07,0x4B,                      /* ldr r3,pFLASH_CTRL_BASE */
+       0x08,0x4C,                      /* ldr r4,FLASHWRITECMD */
+       0x01,0x25,                      /* movs r5, 1 */
+       0x00,0x26,                      /* movs r6, #0 */
 /* mainloop: */
-       0x19,0x60,              /* str  r1, [r3, #0] */
-       0x87,0x59,              /* ldr  r7, [r0, r6] */
-       0x5F,0x60,              /* str  r7, [r3, #4] */
-       0x9C,0x60,              /* str  r4, [r3, #8] */
+       0x19,0x60,                      /* str  r1, [r3, #0] */
+       0x87,0x59,                      /* ldr  r7, [r0, r6] */
+       0x5F,0x60,                      /* str  r7, [r3, #4] */
+       0x9C,0x60,                      /* str  r4, [r3, #8] */
 /* waitloop: */
-       0x9F,0x68,              /* ldr  r7, [r3, #8] */
-       0x2F,0x42,              /* tst  r7, r5 */
-       0xFC,0xD1,              /* bne  waitloop */
-       0x04,0x31,              /* adds r1, r1, #4 */
-       0x04,0x36,              /* adds r6, r6, #4 */
-       0x96,0x42,              /* cmp  r6, r2 */
-       0xF4,0xD1,              /* bne  mainloop */
-       0x00,0xBE,              /* bkpt #0 */
+       0x9F,0x68,                      /* ldr  r7, [r3, #8] */
+       0x2F,0x42,                      /* tst  r7, r5 */
+       0xFC,0xD1,                      /* bne  waitloop */
+       0x04,0x31,                      /* adds r1, r1, #4 */
+       0x04,0x36,                      /* adds r6, r6, #4 */
+       0x96,0x42,                      /* cmp  r6, r2 */
+       0xF4,0xD1,                      /* bne  mainloop */
+       0x00,0xBE,                      /* bkpt #0 */
 /* pFLASH_CTRL_BASE: */
-       0x00,0xD0,0x0F,0x40,    /* .word        0x400FD000 */
+       0x00,0xD0,0x0F,0x40,    /* .word        0x400FD000 */
 /* FLASHWRITECMD: */
        0x01,0x00,0x42,0xA4     /* .word        0xA4420001 */
 };

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)