@@ -392,6 +392,7 @@ struct brcmf_pciedev_info {
392392 bool in_irq ;
393393 struct pci_dev * pdev ;
394394 char fw_name [BRCMF_FW_NAME_LEN ];
395+ char sig_name [BRCMF_FW_NAME_LEN ];
395396 char nvram_name [BRCMF_FW_NAME_LEN ];
396397 char clm_name [BRCMF_FW_NAME_LEN ];
397398 char txcap_name [BRCMF_FW_NAME_LEN ];
@@ -400,8 +401,7 @@ struct brcmf_pciedev_info {
400401 const struct brcmf_pcie_reginfo * reginfo ;
401402 void __iomem * regs ;
402403 void __iomem * tcm ;
403- u32 ram_base ;
404- u32 ram_size ;
404+ u32 fw_size ;
405405 struct brcmf_chip * ci ;
406406 u32 coreid ;
407407 struct brcmf_pcie_shared_info shared ;
@@ -1807,26 +1807,164 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
18071807 return 0 ;
18081808}
18091809
1810- struct brcmf_random_seed_footer {
1810+ struct brcmf_rtlv_footer {
18111811 __le32 length ;
18121812 __le32 magic ;
18131813};
18141814
1815+ struct brcmf_fw_memmap {
1816+ u32 pad1 [8 ];
1817+ u32 vstatus_start ;
1818+ u32 vstatus_end ;
1819+ u32 fw_start ;
1820+ u32 fw_end ;
1821+ u32 sig_start ;
1822+ u32 sig_end ;
1823+ u32 heap_start ;
1824+ u32 heap_end ;
1825+ u32 pad2 [6 ];
1826+ };
1827+
1828+
1829+ #define BRCMF_BL_HEAP_START_GAP 0x1000
1830+ #define BRCMF_BL_HEAP_SIZE 0x10000
18151831#define BRCMF_RANDOM_SEED_MAGIC 0xfeedc0de
18161832#define BRCMF_RANDOM_SEED_LENGTH 0x100
1833+ #define BRCMF_SIG_MAGIC 0xfeedfe51
1834+ #define BRCMF_VSTATUS_MAGIC 0xfeedfe54
1835+ #define BRCMF_VSTATUS_SIZE 0x28
1836+ #define BRCMF_MEMMAP_MAGIC 0xfeedfe53
1837+ #define BRCMF_END_MAGIC 0xfeed0e2d
1838+
1839+ static int brcmf_alloc_rtlv (struct brcmf_pciedev_info * devinfo , u32 * address , u32 type , size_t length )
1840+ {
1841+ struct brcmf_bus * bus = dev_get_drvdata (& devinfo -> pdev -> dev );
1842+ u32 boundary = devinfo -> ci -> rambase + devinfo -> fw_size +
1843+ BRCMF_BL_HEAP_START_GAP + BRCMF_BL_HEAP_SIZE ;
1844+ u32 start_addr ;
1845+ struct brcmf_rtlv_footer footer = {
1846+ .magic = type ,
1847+ };
1848+
1849+ length = ALIGN (length , 4 );
1850+ start_addr = * address - length - sizeof (struct brcmf_rtlv_footer );
1851+
1852+ if (length > 0xffff || start_addr > * address || start_addr < boundary ) {
1853+ brcmf_err (bus , "failed to allocate 0x%zx bytes for rTLV type 0x%x\n" ,
1854+ length , type );
1855+ return - ENOMEM ;
1856+ }
1857+
1858+ /* Random seed does not use the length check code */
1859+ if (type == BRCMF_RANDOM_SEED_MAGIC )
1860+ footer .length = length ;
1861+ else
1862+ footer .length = length | ((length ^ 0xffff ) << 16 );
1863+
1864+ memcpy_toio (devinfo -> tcm + * address - sizeof (struct brcmf_rtlv_footer ),
1865+ & footer , sizeof (struct brcmf_rtlv_footer ));
1866+
1867+ * address = start_addr ;
1868+
1869+ return 0 ;
1870+ }
18171871
1818- static noinline_for_stack void
1819- brcmf_pcie_provide_random_bytes (struct brcmf_pciedev_info * devinfo , u32 address )
1872+ static noinline_for_stack int
1873+ brcmf_pcie_add_random_seed (struct brcmf_pciedev_info * devinfo , u32 * address )
18201874{
1875+ int err ;
18211876 u8 randbuf [BRCMF_RANDOM_SEED_LENGTH ];
18221877
1878+ err = brcmf_alloc_rtlv (devinfo , address ,
1879+ BRCMF_RANDOM_SEED_MAGIC , BRCMF_RANDOM_SEED_LENGTH );
1880+ if (err )
1881+ return err ;
1882+
1883+ /* Some Apple chips/firmwares expect a buffer of random
1884+ * data to be present before NVRAM
1885+ */
1886+ brcmf_dbg (PCIE , "Download random seed\n" );
1887+
18231888 get_random_bytes (randbuf , BRCMF_RANDOM_SEED_LENGTH );
18241889 memcpy_toio (devinfo -> tcm + address , randbuf , BRCMF_RANDOM_SEED_LENGTH );
1890+
1891+ return 0 ;
1892+ }
1893+
1894+ static int brcmf_pcie_add_signature (struct brcmf_pciedev_info * devinfo ,
1895+ u32 * address , const struct firmware * fwsig )
1896+ {
1897+ int err ;
1898+ struct brcmf_fw_memmap memmap ;
1899+
1900+ brcmf_dbg (PCIE , "Download firmware signature\n" );
1901+
1902+ memset (& memmap , 0 , sizeof (memmap ));
1903+
1904+ memmap .sig_end = * address ;
1905+ err = brcmf_alloc_rtlv (devinfo , address , BRCMF_SIG_MAGIC , fwsig -> size );
1906+ if (err )
1907+ return err ;
1908+ memmap .sig_start = * address ;
1909+
1910+ memmap .vstatus_end = * address ;
1911+ err = brcmf_alloc_rtlv (devinfo , address , BRCMF_VSTATUS_MAGIC , BRCMF_VSTATUS_SIZE );
1912+ if (err )
1913+ return err ;
1914+ memmap .vstatus_start = * address ;
1915+
1916+ err = brcmf_alloc_rtlv (devinfo , address , BRCMF_MEMMAP_MAGIC , sizeof (memmap ));
1917+ if (err )
1918+ return err ;
1919+
1920+ memmap .fw_start = devinfo -> ci -> rambase ;
1921+ memmap .fw_end = memmap .fw_start + devinfo -> fw_size ;
1922+ memmap .heap_start = memmap .fw_end + BRCMF_BL_HEAP_START_GAP ;
1923+ memmap .heap_end = memmap .heap_start + BRCMF_BL_HEAP_SIZE ;
1924+
1925+ if (memmap .heap_end > * address )
1926+ return - ENOMEM ;
1927+
1928+ memcpy_toio (devinfo -> tcm + memmap .sig_start , fwsig -> data , fwsig -> size );
1929+ memset_io (devinfo -> tcm + memmap .vstatus_start , 0 , BRCMF_VSTATUS_SIZE );
1930+ memcpy_toio (devinfo -> tcm + * address , & memmap , sizeof (memmap ));
1931+
1932+ err = brcmf_alloc_rtlv (devinfo , address , BRCMF_END_MAGIC , 0 );
1933+ if (err )
1934+ return err ;
1935+
1936+ return 0 ;
1937+ }
1938+
1939+ static int brcmf_pcie_populate_footers (struct brcmf_pciedev_info * devinfo ,
1940+ u32 * address , const struct firmware * fwsig )
1941+ {
1942+ int err ;
1943+
1944+ /* We only do this for Apple firmwares. If any other
1945+ * production firmwares are found to need this, the condition
1946+ * needs to be adjusted.
1947+ */
1948+ if (!devinfo -> fwseed )
1949+ return 0 ;
1950+
1951+ err = brcmf_pcie_add_random_seed (devinfo , address );
1952+ if (err )
1953+ return err ;
1954+
1955+ if (fwsig ) {
1956+ err = brcmf_pcie_add_signature (devinfo , address , fwsig );
1957+ if (err )
1958+ return err ;
1959+ }
1960+
1961+ return 0 ;
18251962}
18261963
18271964static int brcmf_pcie_download_fw_nvram (struct brcmf_pciedev_info * devinfo ,
1828- const struct firmware * fw , void * nvram ,
1829- u32 nvram_len )
1965+ const struct firmware * fw ,
1966+ const struct firmware * fwsig ,
1967+ void * nvram , u32 nvram_len )
18301968{
18311969 struct brcmf_bus * bus = dev_get_drvdata (& devinfo -> pdev -> dev );
18321970 u32 sharedram_addr ;
@@ -1846,44 +1984,39 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
18461984 (void * )fw -> data , fw -> size );
18471985
18481986 resetintr = get_unaligned_le32 (fw -> data );
1987+ devinfo -> fw_size = fw -> size ;
18491988 release_firmware (fw );
18501989
18511990 /* reset last 4 bytes of RAM address. to be used for shared
18521991 * area. This identifies when FW is running
18531992 */
18541993 brcmf_pcie_write_ram32 (devinfo , devinfo -> ci -> ramsize - 4 , 0 );
18551994
1995+ address = devinfo -> ci -> rambase + devinfo -> ci -> ramsize ;
1996+
18561997 if (nvram ) {
18571998 brcmf_dbg (PCIE , "Download NVRAM %s\n" , devinfo -> nvram_name );
1858- address = devinfo -> ci -> rambase + devinfo -> ci -> ramsize -
1859- nvram_len ;
1999+ address -= nvram_len ;
18602000 memcpy_toio (devinfo -> tcm + address , nvram , nvram_len );
18612001 brcmf_fw_nvram_free (nvram );
18622002
1863- if (devinfo -> fwseed ) {
1864- size_t rand_len = BRCMF_RANDOM_SEED_LENGTH ;
1865- struct brcmf_random_seed_footer footer = {
1866- .length = cpu_to_le32 (rand_len ),
1867- .magic = cpu_to_le32 (BRCMF_RANDOM_SEED_MAGIC ),
1868- };
1869-
1870- /* Some chips/firmwares expect a buffer of random
1871- * data to be present before NVRAM
1872- */
1873- brcmf_dbg (PCIE , "Download random seed\n" );
1874-
1875- address -= sizeof (footer );
1876- memcpy_toio (devinfo -> tcm + address , & footer ,
1877- sizeof (footer ));
1878-
1879- address -= rand_len ;
1880- brcmf_pcie_provide_random_bytes (devinfo , address );
1881- }
2003+ err = brcmf_pcie_populate_footers (devinfo , & address , fwsig );
2004+ if (err )
2005+ brcmf_err (bus , "failed to populate firmware footers err=%d\n" , err );
18822006 } else {
18832007 brcmf_dbg (PCIE , "No matching NVRAM file found %s\n" ,
18842008 devinfo -> nvram_name );
18852009 }
18862010
2011+ release_firmware (fwsig );
2012+
2013+ /* Clear free TCM. This isn't really necessary, but it
2014+ * makes debugging memory dumps a lot easier since we
2015+ * don't get a bunch of junk filling up the free space.
2016+ */
2017+ memset_io (devinfo -> tcm + devinfo -> ci -> rambase + devinfo -> fw_size ,
2018+ 0 , address - devinfo -> fw_size - devinfo -> ci -> rambase );
2019+
18872020 sharedram_addr_written = brcmf_pcie_read_ram32 (devinfo ,
18882021 devinfo -> ci -> ramsize -
18892022 4 );
@@ -2269,11 +2402,12 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)
22692402#define BRCMF_PCIE_FW_NVRAM 1
22702403#define BRCMF_PCIE_FW_CLM 2
22712404#define BRCMF_PCIE_FW_TXCAP 3
2405+ #define BRCMF_PCIE_FW_SIG 4
22722406
22732407static void brcmf_pcie_setup (struct device * dev , int ret ,
22742408 struct brcmf_fw_request * fwreq )
22752409{
2276- const struct firmware * fw ;
2410+ const struct firmware * fw , * fwsig ;
22772411 void * nvram ;
22782412 struct brcmf_bus * bus ;
22792413 struct brcmf_pciedev * pcie_bus_dev ;
@@ -2292,6 +2426,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
22922426 brcmf_pcie_attach (devinfo );
22932427
22942428 fw = fwreq -> items [BRCMF_PCIE_FW_CODE ].binary ;
2429+ fwsig = fwreq -> items [BRCMF_PCIE_FW_SIG ].binary ;
22952430 nvram = fwreq -> items [BRCMF_PCIE_FW_NVRAM ].nv_data .data ;
22962431 nvram_len = fwreq -> items [BRCMF_PCIE_FW_NVRAM ].nv_data .len ;
22972432 devinfo -> clm_fw = fwreq -> items [BRCMF_PCIE_FW_CLM ].binary ;
@@ -2302,6 +2437,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
23022437 if (ret ) {
23032438 brcmf_err (bus , "Failed to get RAM info\n" );
23042439 release_firmware (fw );
2440+ release_firmware (fwsig );
23052441 brcmf_fw_nvram_free (nvram );
23062442 goto fail ;
23072443 }
@@ -2313,7 +2449,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
23132449 */
23142450 brcmf_pcie_adjust_ramsize (devinfo , (u8 * )fw -> data , fw -> size );
23152451
2316- ret = brcmf_pcie_download_fw_nvram (devinfo , fw , nvram , nvram_len );
2452+ ret = brcmf_pcie_download_fw_nvram (devinfo , fw , fwsig , nvram , nvram_len );
23172453 if (ret )
23182454 goto fail ;
23192455
@@ -2378,6 +2514,7 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
23782514 { ".txt" , devinfo -> nvram_name },
23792515 { ".clm_blob" , devinfo -> clm_name },
23802516 { ".txcap_blob" , devinfo -> txcap_name },
2517+ { ".sig" , devinfo -> sig_name },
23812518 };
23822519
23832520 fwreq = brcmf_fw_alloc_request (devinfo -> ci -> chip , devinfo -> ci -> chiprev ,
@@ -2388,6 +2525,8 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
23882525 return NULL ;
23892526
23902527 fwreq -> items [BRCMF_PCIE_FW_CODE ].type = BRCMF_FW_TYPE_BINARY ;
2528+ fwreq -> items [BRCMF_PCIE_FW_SIG ].type = BRCMF_FW_TYPE_BINARY ;
2529+ fwreq -> items [BRCMF_PCIE_FW_SIG ].flags = BRCMF_FW_REQF_OPTIONAL ;
23912530 fwreq -> items [BRCMF_PCIE_FW_NVRAM ].type = BRCMF_FW_TYPE_NVRAM ;
23922531 fwreq -> items [BRCMF_PCIE_FW_NVRAM ].flags = BRCMF_FW_REQF_OPTIONAL ;
23932532 fwreq -> items [BRCMF_PCIE_FW_CLM ].type = BRCMF_FW_TYPE_BINARY ;
0 commit comments