⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dloadarm.c

📁 在高通的手机平台下,一个下载手机.bin文件到手机的flash中的工具,包含PC端的程序代码和运行在基带处理器中的代码.
💻 C
📖 第 1 页 / 共 4 页
字号:
===========================================================================*/

static void transmit_response
(
  response_code_type rsp
    /* Type of response to transmit */
)

{
  const byte *pkt;
    /* Pointer into the packet being transmitted */

/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  pkt = response_table[rsp];             /* Find the packet to transmit */

  uart_transmit_byte(ASYNC_HDLC_FLAG);      /* Supply the leading flag  */

  do
    {
    uart_transmit_byte(*pkt);         /* Transmit bytes from the buffer */
    }
  while (*pkt++ != ASYNC_HDLC_FLAG);  /* Until we've transmitted a flag */

} /* transmit_response() */


/*===========================================================================

FUNCTION rcv_packet

DESCRIPTION
  This function receives a complete packet using the generic UART
  service uart_receive_byte.  It takes care of the async-HDLC state
  machine, enforces a minimum packet length of 1 byte plus CRC, and
  checks the CRC on the fly.

DEPENDENCIES
  Uses the crc table.

RETURN VALUE
  Once a good packet is received, returns its length including
  but not including flags or byte stuffing escapes.

SIDE EFFECTS
  If a NAK-able packet error is detected, this function generates a
  suitable NAK response and does not return until a good packet is
  received.

  The watchdog is reset.
===========================================================================*/

static word rcv_packet
(
  byte *buf
    /* Pointer to the packet buffer for receiving the packet */
)

{

  enum
    {
    HDLC_HUNT_FOR_FLAG,     /* Waiting for a flag to start a packet       */
    HDLC_GOT_FLAG,          /* Have a flag, expecting the packet to start */
    HDLC_GATHER,            /* In the middle of a packet                  */
    HDLC_PACKET_RCVD        /* Now have received a complete packet        */
    } state;
    /* State variable for decoding async HDLC */

  int   chr;
    /* Current character being received */

  word  len;
    /* Length of packet collected so far */

  word  crc=0;
    /* Cyclic Redundancy Check, computed as we go. */

    /*lint -esym(644,len,crc) */
    /* Lint can't tell that the state machine guarantees that
       we initialize len and crc before use */

/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /* Look at characters and try to find a valid async-HDLC packet of
     length at least MIN_PACKET_LEN with a valid CRC.
     Keep looking until we find one. */
  len=0;
  for (state = HDLC_HUNT_FOR_FLAG; state != HDLC_PACKET_RCVD; /* nil */)
    {
    BOOTHW_KICK_WATCHDOG();                 /* Don't let the watchdog expire */

    chr = uart_receive_byte();       /* Get next character (wait for it) */

    if (chr == UART_RX_ERR)          /* If it's an error ... */
      {
      state = HDLC_HUNT_FOR_FLAG;             /* Start over. */
      continue;
      }

    /* initial communication timed out */
    if (chr == UART_TIMEOUT)
      {
        boot_powerdown_entry();
      }

    switch(state)                  /* Process according to which state */
      {
      /*lint -esym(788,HDLC_PACKET_RCVD)  No need to deal with HDLC_PACKET_RCVD
         since we're in a loop that guarantees we're not in that state. */

      case HDLC_HUNT_FOR_FLAG:         /* We're looking for a flag ... */
        if (chr == ASYNC_HDLC_FLAG)    /*   and we got one ...         */
          {
          state = HDLC_GOT_FLAG;       /*   so go on to the next step. */
          }
        break;

/*-   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -*/

      case HDLC_GOT_FLAG:              /* Had a flag, now expect a packet */
        if (chr == ASYNC_HDLC_FLAG)    /* Oops, another flag.  No change. */
          {
          break;
          }
        else
          {                            /* Ah, we can really begin a packet */
          len = 0;                     /* The packet starts out empty      */
          crc = CRC_16_L_SEED;         /* and the CRC in its initial state */
          state = HDLC_GATHER;         /* and we begin to gather a packet  */
          /* Fall through */           /*   (starting with this byte)      */
          }

/*-   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -*/

      case HDLC_GATHER:                   /* We're gathering a packet      */
        if (chr == ASYNC_HDLC_FLAG)       /* We've reached the end         */
          {
          if (len < MIN_PACKET_LEN)       /* Reject any too-short packets  */
            {
            transmit_response(NAK_EARLY_END);            /* Send NAK       */
            state = HDLC_HUNT_FOR_FLAG;                  /* Start over     */
            }
          else if (crc != CRC_16_L_OK_NEG)      /* Reject any with bad CRC */
            {
            transmit_response(NAK_INVALID_FCS);          /* Send NAK       */
            state = HDLC_HUNT_FOR_FLAG;                  /* Start over     */
            }
          else                                 /* Yay, it's a good packet! */
            {
            state = HDLC_PACKET_RCVD;                    /* Done for now   */
            }
          break;           /* However it turned out, this packet is over.  */
          }

        /* It wasn't a flag, so we're still inside the packet. */

        if (chr == ASYNC_HDLC_ESC)               /* If it was an ESC       */
          {
          chr = uart_receive_byte();             /* Get the escaped byte   */

          if (chr == UART_RX_ERR)                /* If there was an error, */
            {
            state = HDLC_HUNT_FOR_FLAG;          /* Start over             */
            break;
            }

          chr ^= ASYNC_HDLC_ESC_MASK;            /* Otherwise, de-mask it  */

          /* No break; process the de-masked byte normally */
          }

        if (len >= MAX_PACKET_LEN)               /* Make sure there's room */
          {
          transmit_response(NAK_TOO_LARGE);      /* Oops, buffer too full  */
          state = HDLC_HUNT_FOR_FLAG;            /* Start over             */
          }
        else
          {
          buf[len++] = (byte) chr;                   /* Add byte to buffer */
          crc = CRC_16_L_STEP(crc, (word) chr);      /* Update the CRC     */
          }

        break;

/*-   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -*/

      default:       /* Shouldn't happen with an enum, but for safety ...  */
        state = HDLC_HUNT_FOR_FLAG;                  /* Start over         */
        break;

      }/* switch on state */
    }/* for (packet not found) */

  return len;

} /* rcv_packet() */


/*===========================================================================

FUNCTION write_cmd

DESCRIPTION
  This function processes a write command packet.  Pending a valid address
  range, the data is written to RAM.  Note that an offset needs to be added
  to the address to move it to the target RAM location.  The Intel MCS86 hex
  file format does not support the address range for the ARM, therefore, it
  is created with an implicit start address of 0, which then needs to be
  offset into the intended address range.

DEPENDENCIES
  None.

RETURN VALUE
  None.

SIDE EFFECTS
  None.

===========================================================================*/

static void write_cmd
(
  byte *cmd_buf,
    /* Pointer to the received command packet */

  word  cmd_len
    /* Number of bytes received in the command packet */
)

{
  dword                addr;    /* destination address for write */
  byte                *w_addr;  /* offset address */
  byte                *start;   /* start location for write - includes offset */
  byte                *data;    /* pointer to bytes of data */
  word                 len;     /* number of bytes to write */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  if (cmd_len < WRITE_SIZ)       /* Make sure at least the header arrived  */
    {
    transmit_response(NAK_EARLY_END);        /* Nope, packet ended early   */
    return;
    }

  /* Verify that a valid security code was previously received */
  if (!sec_code_unlocked)
    {
    transmit_response(NAK_NO_SEC_CODE);      /* It wasn't, so complain     */
    return;
    }

  B_PTR(addr)[3] = 0;          /* Extract destination address from packet  */
  B_PTR(addr)[2] = cmd_buf[1];
  B_PTR(addr)[1] = cmd_buf[2];
  B_PTR(addr)[0] = cmd_buf[3];

  B_PTR(len)[1]  = cmd_buf[4];      /* Extract write length from packet    */
  B_PTR(len)[0]  = cmd_buf[5];

  if (len + WRITE_SIZ != cmd_len)  /* Packet must be exactly the right len */
    {
    transmit_response(NAK_INVALID_LEN);      /* It wasn't, so complain     */
    return;
    }

  /* convert addresses to RAM address range */
  w_addr = (byte *) (addr+DLOAD_OFFSET);
  start = (byte *) (addr+DLOAD_OFFSET);

  /* check address range limits */
  if (w_addr < (byte*)DLOAD_BASE || (w_addr+len) >= (byte*)DLOAD_LIMIT)
  {
     transmit_response(NAK_INVALID_DEST);
     return;
  }

  /* start of data portion of packet */
  data = (byte *) (cmd_buf+6);

  /* perform the write to memory */
  while (w_addr <= (start + len)) {
     *w_addr++ = *data++;
  }

  /* everything ok */
  transmit_response(ACK);

} /* write_cmd() */


/*===========================================================================

FUNCTION erase_cmd

DESCRIPTION
  This function processes an erase command packet.  Pending a valid address
  range, the specified area is erased from RAM.  Note that an offset needs to be added
  to the address to move it to the target RAM location.  The Intel MCS86 hex
  file format does not support the address range for the ARM, therefore, it
  is created with an implicit start address of 0, which then needs to be
  offset into the intended address range.

DEPENDENCIES
  None.

RETURN VALUE
  None.

SIDE EFFECTS
  None.

===========================================================================*/

static void erase_cmd
(
  byte *cmd_buf,
    /* Pointer to the received command packet */

  word  cmd_len
    /* Number of bytes received in the command packet */
)

{
  dword                addr;     /* destination address */
  dword                len;      /* number of bytes to erase */
  byte                 *e_addr;  /* offset address */
  byte                 *start;   /* start location for erase */
  byte                 *data;    /* pointer to bytes of data */

/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  if (cmd_len != ERASE_SIZ)          /* Make sure the whole packet arrived */
    {
      transmit_response(NAK_EARLY_END);          /* Nope, packet ended early */
      return;
    }

  /* Verify that a valid security code was previously received */
  if (!sec_code_unlocked)
    {
    transmit_response(NAK_NO_SEC_CODE);      /* It wasn't, so complain     */
    return;
    }

  B_PTR(addr)[3] = 0;           /* Extract destination address from packet */
  B_PTR(addr)[2] = cmd_buf[1];
  B_PTR(addr)[1] = cmd_buf[2];
  B_PTR(addr)[0] = cmd_buf[3];

  B_PTR(len)[3]  = 0;           /* Extract write length from packet        */
  B_PTR(len)[2]  = cmd_buf[4];
  B_PTR(len)[1]  = cmd_buf[5];
  B_PTR(len)[0]  = cmd_buf[6];

  /* convert addresses to RAM address range */
  e_addr = (byte *) (addr+DLOAD_OFFSET);
  start = (byte *) (addr+DLOAD_OFFSET);

  /* check address range limits */
  if (e_addr < (byte*)DLOAD_BASE || (e_addr+len) >= (byte*)DLOAD_LIMIT)
    {
      transmit_response(NAK_INVALID_DEST);
    }


  /* start of data portion of packet */
  data = (byte *) (cmd_buf+6);

  /* erase the memory */
  while (e_addr <= (start + len)) {
    *e_addr++ = 0x00;
  }

  /* everything ok */
  transmit_response(ACK);

} /* erase_cmd() */


/*===========================================================================

FUNCTION go_cmd

DESCRIPTION
  This function processes a GO command packet, which requires the
  transfer of execution control to a specified address.

DEPENDENCIES
  None.

RETURN VALUE
  Generally, this function does not return, since the entry point of
  the downloaded module is not supposed to return.  However, if the
  called code does return, this function returns (void).

SIDE EFFECTS
  None.

===========================================================================*/

static void go_cmd
(
  byte *cmd_buf,
    /* Pointer to the received command packet */

  word  cmd_len
    /* Number of bytes received in the command packet */
)

{
  void  (* jump_point)(void);  /* address of the routine to run */

/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /* Make sure the whole packet arrived. */
  if (cmd_len != GO_SIZ)
    {
    transmit_response(NAK_EARLY_END);  /* Nope, packet ended early         */
    return;
    }

  /* Verify that a valid security code was previously received */
  if (!sec_code_unlocked)
    {
    transmit_response(NAK_NO_SEC_CODE);      /* It wasn't, so complain     */
    return;
    }

  /* Construct a pointer to the destination address */
  B_PTR(jump_point)[3] = cmd_buf[1];   /* Extract code segment from packet */
  B_PTR(jump_point)[2] = cmd_buf[2];
  B_PTR(jump_point)[1] = cmd_buf[3];   /* Extract code offset from packet  */
  B_PTR(jump_point)[0] = cmd_buf[4];

  transmit_response(ACK);          /* Have to send the ACK before GOing. */

  uart_drain();                    /* Make sure the response gets out */

  jump_point();                    /* Call the routine */

  /* It really shouldn't return, but just in case it does we will
     continue with packet processing and hope everything is still
     properly set up for that. */

} /* go_cmd() */


/*============================================================================

 FUNCTION UNLOCK_CMD

 DESCRIPTION
   Process an unlock command.

   If the security code contained in the unlock command does not match
   the security code stored in flash memory, the phone will be
   powered-down.  If the codes do match, then secure download functions
   will be unlocked.

 FORMAL ARGUMENTS
   None

 DEPENDENCIES
   None

 RETURN VALUE
   An error flag is returned: zero indicates no errors occurred,
   one indicates that an error did occur.  However, if an incorrect
   security code is contained in the unlock command, the phone will
   be powered-down and this function will not return.

 SIDE EFFECTS
   None

============================================================================*/
static void unlock_cmd
(
  byte *cmd_buf,
    /* Pointer to the received command packet */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -