@@ -388,6 +388,7 @@ struct brcmf_pciedev_info {
388388 bool in_irq ;
389389 struct pci_dev * pdev ;
390390 char fw_name [BRCMF_FW_NAME_LEN ];
391+ char sig_name [BRCMF_FW_NAME_LEN ];
391392 char nvram_name [BRCMF_FW_NAME_LEN ];
392393 char clm_name [BRCMF_FW_NAME_LEN ];
393394 char txcap_name [BRCMF_FW_NAME_LEN ];
@@ -396,8 +397,7 @@ struct brcmf_pciedev_info {
396397 const struct brcmf_pcie_reginfo * reginfo ;
397398 void __iomem * regs ;
398399 void __iomem * tcm ;
399- u32 ram_base ;
400- u32 ram_size ;
400+ u32 fw_size ;
401401 struct brcmf_chip * ci ;
402402 u32 coreid ;
403403 struct brcmf_pcie_shared_info shared ;
@@ -1800,26 +1800,164 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
18001800 return 0 ;
18011801}
18021802
1803- struct brcmf_random_seed_footer {
1803+ struct brcmf_rtlv_footer {
18041804 __le32 length ;
18051805 __le32 magic ;
18061806};
18071807
1808+ struct brcmf_fw_memmap {
1809+ u32 pad1 [8 ];
1810+ u32 vstatus_start ;
1811+ u32 vstatus_end ;
1812+ u32 fw_start ;
1813+ u32 fw_end ;
1814+ u32 sig_start ;
1815+ u32 sig_end ;
1816+ u32 heap_start ;
1817+ u32 heap_end ;
1818+ u32 pad2 [6 ];
1819+ };
1820+
1821+
1822+ #define BRCMF_BL_HEAP_START_GAP 0x1000
1823+ #define BRCMF_BL_HEAP_SIZE 0x10000
18081824#define BRCMF_RANDOM_SEED_MAGIC 0xfeedc0de
18091825#define BRCMF_RANDOM_SEED_LENGTH 0x100
1826+ #define BRCMF_SIG_MAGIC 0xfeedfe51
1827+ #define BRCMF_VSTATUS_MAGIC 0xfeedfe54
1828+ #define BRCMF_VSTATUS_SIZE 0x28
1829+ #define BRCMF_MEMMAP_MAGIC 0xfeedfe53
1830+ #define BRCMF_END_MAGIC 0xfeed0e2d
1831+
1832+ static int brcmf_alloc_rtlv (struct brcmf_pciedev_info * devinfo , u32 * address , u32 type , size_t length )
1833+ {
1834+ struct brcmf_bus * bus = dev_get_drvdata (& devinfo -> pdev -> dev );
1835+ u32 boundary = devinfo -> ci -> rambase + devinfo -> fw_size +
1836+ BRCMF_BL_HEAP_START_GAP + BRCMF_BL_HEAP_SIZE ;
1837+ u32 start_addr ;
1838+ struct brcmf_rtlv_footer footer = {
1839+ .magic = type ,
1840+ };
1841+
1842+ length = ALIGN (length , 4 );
1843+ start_addr = * address - length - sizeof (struct brcmf_rtlv_footer );
1844+
1845+ if (length > 0xffff || start_addr > * address || start_addr < boundary ) {
1846+ brcmf_err (bus , "failed to allocate 0x%zx bytes for rTLV type 0x%x\n" ,
1847+ length , type );
1848+ return - ENOMEM ;
1849+ }
1850+
1851+ /* Random seed does not use the length check code */
1852+ if (type == BRCMF_RANDOM_SEED_MAGIC )
1853+ footer .length = length ;
1854+ else
1855+ footer .length = length | ((length ^ 0xffff ) << 16 );
1856+
1857+ memcpy_toio (devinfo -> tcm + * address - sizeof (struct brcmf_rtlv_footer ),
1858+ & footer , sizeof (struct brcmf_rtlv_footer ));
1859+
1860+ * address = start_addr ;
1861+
1862+ return 0 ;
1863+ }
18101864
1811- static noinline_for_stack void
1812- brcmf_pcie_provide_random_bytes (struct brcmf_pciedev_info * devinfo , u32 address )
1865+ static noinline_for_stack int
1866+ brcmf_pcie_add_random_seed (struct brcmf_pciedev_info * devinfo , u32 * address )
18131867{
1868+ int err ;
18141869 u8 randbuf [BRCMF_RANDOM_SEED_LENGTH ];
18151870
1871+ err = brcmf_alloc_rtlv (devinfo , address ,
1872+ BRCMF_RANDOM_SEED_MAGIC , BRCMF_RANDOM_SEED_LENGTH );
1873+ if (err )
1874+ return err ;
1875+
1876+ /* Some Apple chips/firmwares expect a buffer of random
1877+ * data to be present before NVRAM
1878+ */
1879+ brcmf_dbg (PCIE , "Download random seed\n" );
1880+
18161881 get_random_bytes (randbuf , BRCMF_RANDOM_SEED_LENGTH );
18171882 memcpy_toio (devinfo -> tcm + address , randbuf , BRCMF_RANDOM_SEED_LENGTH );
1883+
1884+ return 0 ;
1885+ }
1886+
1887+ static int brcmf_pcie_add_signature (struct brcmf_pciedev_info * devinfo ,
1888+ u32 * address , const struct firmware * fwsig )
1889+ {
1890+ int err ;
1891+ struct brcmf_fw_memmap memmap ;
1892+
1893+ brcmf_dbg (PCIE , "Download firmware signature\n" );
1894+
1895+ memset (& memmap , 0 , sizeof (memmap ));
1896+
1897+ memmap .sig_end = * address ;
1898+ err = brcmf_alloc_rtlv (devinfo , address , BRCMF_SIG_MAGIC , fwsig -> size );
1899+ if (err )
1900+ return err ;
1901+ memmap .sig_start = * address ;
1902+
1903+ memmap .vstatus_end = * address ;
1904+ err = brcmf_alloc_rtlv (devinfo , address , BRCMF_VSTATUS_MAGIC , BRCMF_VSTATUS_SIZE );
1905+ if (err )
1906+ return err ;
1907+ memmap .vstatus_start = * address ;
1908+
1909+ err = brcmf_alloc_rtlv (devinfo , address , BRCMF_MEMMAP_MAGIC , sizeof (memmap ));
1910+ if (err )
1911+ return err ;
1912+
1913+ memmap .fw_start = devinfo -> ci -> rambase ;
1914+ memmap .fw_end = memmap .fw_start + devinfo -> fw_size ;
1915+ memmap .heap_start = memmap .fw_end + BRCMF_BL_HEAP_START_GAP ;
1916+ memmap .heap_end = memmap .heap_start + BRCMF_BL_HEAP_SIZE ;
1917+
1918+ if (memmap .heap_end > * address )
1919+ return - ENOMEM ;
1920+
1921+ memcpy_toio (devinfo -> tcm + memmap .sig_start , fwsig -> data , fwsig -> size );
1922+ memset_io (devinfo -> tcm + memmap .vstatus_start , 0 , BRCMF_VSTATUS_SIZE );
1923+ memcpy_toio (devinfo -> tcm + * address , & memmap , sizeof (memmap ));
1924+
1925+ err = brcmf_alloc_rtlv (devinfo , address , BRCMF_END_MAGIC , 0 );
1926+ if (err )
1927+ return err ;
1928+
1929+ return 0 ;
1930+ }
1931+
1932+ static int brcmf_pcie_populate_footers (struct brcmf_pciedev_info * devinfo ,
1933+ u32 * address , const struct firmware * fwsig )
1934+ {
1935+ int err ;
1936+
1937+ /* We only do this for Apple firmwares. If any other
1938+ * production firmwares are found to need this, the condition
1939+ * needs to be adjusted.
1940+ */
1941+ if (!devinfo -> otp .valid )
1942+ return 0 ;
1943+
1944+ err = brcmf_pcie_add_random_seed (devinfo , address );
1945+ if (err )
1946+ return err ;
1947+
1948+ if (fwsig ) {
1949+ err = brcmf_pcie_add_signature (devinfo , address , fwsig );
1950+ if (err )
1951+ return err ;
1952+ }
1953+
1954+ return 0 ;
18181955}
18191956
18201957static int brcmf_pcie_download_fw_nvram (struct brcmf_pciedev_info * devinfo ,
1821- const struct firmware * fw , void * nvram ,
1822- u32 nvram_len )
1958+ const struct firmware * fw ,
1959+ const struct firmware * fwsig ,
1960+ void * nvram , u32 nvram_len )
18231961{
18241962 struct brcmf_bus * bus = dev_get_drvdata (& devinfo -> pdev -> dev );
18251963 u32 sharedram_addr ;
@@ -1839,44 +1977,39 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
18391977 (void * )fw -> data , fw -> size );
18401978
18411979 resetintr = get_unaligned_le32 (fw -> data );
1980+ devinfo -> fw_size = fw -> size ;
18421981 release_firmware (fw );
18431982
18441983 /* reset last 4 bytes of RAM address. to be used for shared
18451984 * area. This identifies when FW is running
18461985 */
18471986 brcmf_pcie_write_ram32 (devinfo , devinfo -> ci -> ramsize - 4 , 0 );
18481987
1988+ address = devinfo -> ci -> rambase + devinfo -> ci -> ramsize ;
1989+
18491990 if (nvram ) {
18501991 brcmf_dbg (PCIE , "Download NVRAM %s\n" , devinfo -> nvram_name );
1851- address = devinfo -> ci -> rambase + devinfo -> ci -> ramsize -
1852- nvram_len ;
1992+ address -= nvram_len ;
18531993 memcpy_toio (devinfo -> tcm + address , nvram , nvram_len );
18541994 brcmf_fw_nvram_free (nvram );
18551995
1856- if (devinfo -> otp .valid ) {
1857- size_t rand_len = BRCMF_RANDOM_SEED_LENGTH ;
1858- struct brcmf_random_seed_footer footer = {
1859- .length = cpu_to_le32 (rand_len ),
1860- .magic = cpu_to_le32 (BRCMF_RANDOM_SEED_MAGIC ),
1861- };
1862-
1863- /* Some Apple chips/firmwares expect a buffer of random
1864- * data to be present before NVRAM
1865- */
1866- brcmf_dbg (PCIE , "Download random seed\n" );
1867-
1868- address -= sizeof (footer );
1869- memcpy_toio (devinfo -> tcm + address , & footer ,
1870- sizeof (footer ));
1871-
1872- address -= rand_len ;
1873- brcmf_pcie_provide_random_bytes (devinfo , address );
1874- }
1996+ err = brcmf_pcie_populate_footers (devinfo , & address , fwsig );
1997+ if (err )
1998+ brcmf_err (bus , "failed to populate firmware footers err=%d\n" , err );
18751999 } else {
18762000 brcmf_dbg (PCIE , "No matching NVRAM file found %s\n" ,
18772001 devinfo -> nvram_name );
18782002 }
18792003
2004+ release_firmware (fwsig );
2005+
2006+ /* Clear free TCM. This isn't really necessary, but it
2007+ * makes debugging memory dumps a lot easier since we
2008+ * don't get a bunch of junk filling up the free space.
2009+ */
2010+ memset_io (devinfo -> tcm + devinfo -> ci -> rambase + devinfo -> fw_size ,
2011+ 0 , address - devinfo -> fw_size - devinfo -> ci -> rambase );
2012+
18802013 sharedram_addr_written = brcmf_pcie_read_ram32 (devinfo ,
18812014 devinfo -> ci -> ramsize -
18822015 4 );
@@ -2262,11 +2395,12 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)
22622395#define BRCMF_PCIE_FW_NVRAM 1
22632396#define BRCMF_PCIE_FW_CLM 2
22642397#define BRCMF_PCIE_FW_TXCAP 3
2398+ #define BRCMF_PCIE_FW_SIG 4
22652399
22662400static void brcmf_pcie_setup (struct device * dev , int ret ,
22672401 struct brcmf_fw_request * fwreq )
22682402{
2269- const struct firmware * fw ;
2403+ const struct firmware * fw , * fwsig ;
22702404 void * nvram ;
22712405 struct brcmf_bus * bus ;
22722406 struct brcmf_pciedev * pcie_bus_dev ;
@@ -2285,6 +2419,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
22852419 brcmf_pcie_attach (devinfo );
22862420
22872421 fw = fwreq -> items [BRCMF_PCIE_FW_CODE ].binary ;
2422+ fwsig = fwreq -> items [BRCMF_PCIE_FW_SIG ].binary ;
22882423 nvram = fwreq -> items [BRCMF_PCIE_FW_NVRAM ].nv_data .data ;
22892424 nvram_len = fwreq -> items [BRCMF_PCIE_FW_NVRAM ].nv_data .len ;
22902425 devinfo -> clm_fw = fwreq -> items [BRCMF_PCIE_FW_CLM ].binary ;
@@ -2295,6 +2430,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
22952430 if (ret ) {
22962431 brcmf_err (bus , "Failed to get RAM info\n" );
22972432 release_firmware (fw );
2433+ release_firmware (fwsig );
22982434 brcmf_fw_nvram_free (nvram );
22992435 goto fail ;
23002436 }
@@ -2306,7 +2442,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
23062442 */
23072443 brcmf_pcie_adjust_ramsize (devinfo , (u8 * )fw -> data , fw -> size );
23082444
2309- ret = brcmf_pcie_download_fw_nvram (devinfo , fw , nvram , nvram_len );
2445+ ret = brcmf_pcie_download_fw_nvram (devinfo , fw , fwsig , nvram , nvram_len );
23102446 if (ret )
23112447 goto fail ;
23122448
@@ -2371,6 +2507,7 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
23712507 { ".txt" , devinfo -> nvram_name },
23722508 { ".clm_blob" , devinfo -> clm_name },
23732509 { ".txcap_blob" , devinfo -> txcap_name },
2510+ { ".sig" , devinfo -> sig_name },
23742511 };
23752512
23762513 fwreq = brcmf_fw_alloc_request (devinfo -> ci -> chip , devinfo -> ci -> chiprev ,
@@ -2381,6 +2518,8 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
23812518 return NULL ;
23822519
23832520 fwreq -> items [BRCMF_PCIE_FW_CODE ].type = BRCMF_FW_TYPE_BINARY ;
2521+ fwreq -> items [BRCMF_PCIE_FW_SIG ].type = BRCMF_FW_TYPE_BINARY ;
2522+ fwreq -> items [BRCMF_PCIE_FW_SIG ].flags = BRCMF_FW_REQF_OPTIONAL ;
23842523 fwreq -> items [BRCMF_PCIE_FW_NVRAM ].type = BRCMF_FW_TYPE_NVRAM ;
23852524 fwreq -> items [BRCMF_PCIE_FW_NVRAM ].flags = BRCMF_FW_REQF_OPTIONAL ;
23862525 fwreq -> items [BRCMF_PCIE_FW_CLM ].type = BRCMF_FW_TYPE_BINARY ;
0 commit comments